Socket是什么
Socket 也叫“套接字”,是两台机器间通信的端点,也就是成对存在才能通信。Socket 本质是编程接口,对TCP/IP的封装。
如果说HTTP是轿车,提供了封装或者显示数据的具体形式;Socket 就是发动机,提供了网络通信的能力。(来自网络)
(来自网络)
在Java 开发中使用Socket 时会常用到两个类,都在java.net 包中:Socket和ServerSocket
ServerSocket用于服务端,Socket 刚是哪里都得使用,它是连接建立后的实例所对应的类。在两个应用程序连接成功时,这两个应用程序两端都会产生一个Socket 实例,我们就是通过操作这两个实例来完成通信的内容的。需要说明的是,Socket和ServerSocket并没什么差别,它们的具体实现都是通过子类SocketImpl来完成。
Socket 连接过程
总的来说分三步:服务器监听,客户端请求,连接确认
1.服务端的Socket 并不定位具体客户端的Socket,而是将自己处于一个等待连接的状态,监听网络的连接状态。
2.客户端Socket想提出连接请求,那它就得说明连接的服务器地址和端口号。
3.服务器Socket监听到客户端连接请求后,会响应客户端Socket 的请求了。它在此时会建立一个新的线程,把服务器的Socket 描述发给客户端,客户端确认了此描述,连接就算建立好了。服务器的Socket 会继续它的监听状态,等待其他连接。
Socket Java例子
服务端
package com.hlm.socket;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
public class SocketServer {
public static void main(String[] args) throws IOException{
//创建Socket
@SuppressWarnings("resource")
ServerSocket ssocket = new ServerSocket(888);
System.out.println("《服务器》:服务器已开启,想连的小伙伴抓紧时间啦!");
//等待连接的Socket,他在等生成实例,生成了便说明有连接成功了
Socket socket ;
while(true){
socket = ssocket.accept();
//每接收到一个客户端连接刚创建一个线程来处理该连接的情况
Thread t = new Thread(new MyRunnable(socket));
t.start();
}
}
//模仿数据库存用户的账号和密码
public static HashMap<String ,String> accountMap = new HashMap<String ,String>();
static{
accountMap.put("小明","123456");
accountMap.put("小红","888888");
accountMap.put("小强","666666");
accountMap.put("王二","987654");
}
}
//创建一个内部类来为每个连接处理线程情况
class MyRunnable implements Runnable{
Socket socket ;
public MyRunnable(){ }
public MyRunnable(Socket socket){
this.socket = socket;
}
@Override
public void run() {
if(socket == null ){
return ;
}
InputStream ins = null;
BufferedReader br = null;
OutputStream os = null;
PrintWriter pw = null;
try {
//连接上之后获取对方传过来的信息
ins = socket.getInputStream();
//将字节流转为字符
br = new BufferedReader(new InputStreamReader(ins));
StringBuffer info = new StringBuffer();
String linedata = null;
//将信息收信进info
while((linedata = br.readLine() ) != null){
info.append(linedata);
}
String name = "";
String password = "";
String resultStr="错误的用户名或密码 ";
//"name:小明;password:123456"
//将信息按约定的解析
String[] list = info.toString()==null?null:info.toString().split(";");
for(String str : list){
if(str.startsWith("name:")){
name = str.replace("name:", "");
}else if(str.startsWith("password:")){
password = str.replace("password:", "");
}
}
String mypassword = SocketServer.accountMap.get(name);
if(mypassword !=null && mypassword.equals(password)){
resultStr = "登录成功!";
}
//关闭接收数据
socket.shutdownInput();
//将结果返回给客户端
os = socket.getOutputStream();
pw = new PrintWriter(os);
pw.write(resultStr);
System.out.println("《服务器》:请求内容为-->"+info+";请求结果为-->"+resultStr);
//将结果刷走
pw.flush();
//关闭输出流
socket.shutdownOutput();
} catch (IOException e) {
e.printStackTrace();
}finally{
//关闭所在资源(与创建反序)
try {
pw.close();
os.close();
br.close();
ins.close();
if(null != socket) {
socket.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
客户端
package com.hlm.socket;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
public class SocketClient {
public static void main(String[] args) throws UnknownHostException, IOException {
//小明登录
getSocket(1 , "name:小明;password:123456");
//小红登录
getSocket(2 , "name:小红;password:888888");
//小强登录
getSocket(3 , "name:小强;password:666666");
//王二登录
getSocket(4 , "name:王二;password:忘了");
//老王登录
getSocket(5 , "name:老王;password:123456");
}
/**
* 建立Socket 连接方法
* @param num
* @param msg
*/
public static void getSocket(int num , String msg) {
BufferedReader br = null;
InputStream ins = null;
PrintWriter pw = null;
OutputStream os = null;
Socket sk = null ;
try{
String address = "localhost";
int port = 888;
System.out.println("《客户端"+num+"》:我要登录啦!");
sk = new Socket(address,port);
os = sk.getOutputStream();
pw = new PrintWriter(os);
//pw.write("name:小明;password:123456");
pw.write(msg);
pw.flush();
sk.shutdownOutput();
ins = sk.getInputStream();
br = new BufferedReader(new InputStreamReader(ins));
String str = null ;
StringBuffer sb = new StringBuffer();
while((str = br.readLine()) !=null){
sb.append(str);
}
System.out.println("《客户端"+num+"》:返回的结果为-->"+sb);
}catch(IOException e){
e.printStackTrace();
}finally{
try {
br.close();
pw.close();
ins.close();
br.close();
if(null != sk) {
sk.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
启动服务器后
运行客户端
此时服务器打印
Socket 的更多API可以查询:
20180609