目录
一、socket学前基础(TCP的三次握手和四次挥手)
1、服务端和客户端如果想要建立连接,就要总共发送三个包来确立连接
第一次握手:Client将标志位SYN置为1,随机产生一个值seq=J,并将该数据包发送给Server, Client进入SYN_SENT状态,等待Server确认
第二次握手:Server收到数据包后由标志位SYN=1知道Client请求建立连接,Server将标志位 SYN和ACK都置为1,ack=J+1,随机产生一个值seq=K,并将该数据包发送给Client以确认连接请求 ,Server进入SYN_RCVD状态。
第三次握手:Client收到确认后,检查ack是否为J+1,ACK是否为1,如果正确则将标志位ACK 置为1,ack=K+1,并将该数据包发送给Server,Server检查ack是否为K+1,ACK是否为1,如果正确则 连接建立成功,Client和Server进入ESTABLISHED状态,完成三次握手,随后Client与Server之间可以 开始传输数据了。
2、四次挥手,终止TCP连接,就是指断开一个TCP连接时,需要客户端和服务端总共发送4个包以确认连接的断开。 在Socket编程中,这一过程由客户端或服务端任一方执行close来触发
第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入 FIN_WAIT_1状态
第二次挥手:Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(与SYN相同, 一个FIN占用一个序号),Server进入CLOSE_WAIT状态。
第三次挥手:Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK 状态。
第四次挥手:Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态
二、为什么要使用socket
socket用于即时通信,是长连接,在传统的http请求中,随着服务端的返回给客户端消息,两者之间的两者之间的关联就消失了,所以服务端想要主动联系客户端就得考轮询的方式,但是这种轮询比较耗费性能的,既要消耗客户端性能,又消耗服务器资源,于是有了长连接的概念。
三、什么是socket
socket是用来描述IP地址和端口,是通信链的句柄,应用程序可以通过socket向网络发送请求或应答请求,socket支持TCP/IP协议的网络通讯基本操作单元,是对网络通信过程中端点的抽象描述包含了网络通信过程中的五种必须信息:链接所使用的协议;本地主机的ip地址;本机端口号;目的主机的ip地址;目的主机的端口号
四、socket的简单代码实现
服务端
Step 1:创建ServerSocket对象,绑定监听的端口
Step 2:调用accept()方法监听客户端的请求
Step 3:连接建立后,通过输入流读取客户端发送的请求信息
Step 4:通过输出流向客户端发送响应信息
Step 5:关闭相关资源
public class SocketServer {
public static void main(String[] args) throws IOException {
//1.创建一个服务器端Socket,即ServerSocket,指定绑定的端口,并监听此端口
ServerSocket serverSocket = new ServerSocket(12345);
InetAddress address = InetAddress.getLocalHost();
String ip = address.getHostAddress();
Socket socket = null;
//2.调用accept()等待客户端连接
System.out.println("~~~服务端已就绪,等待客户端接入~,服务端ip地址: " + ip);
socket = serverSocket.accept();
//3.连接后获取输入流,读取客户端信息
InputStream is=null;
InputStreamReader isr=null;
BufferedReader br=null;
OutputStream os=null;
PrintWriter pw=null;
is = socket.getInputStream(); //获取输入流
isr = new InputStreamReader(is,"UTF-8");
br = new BufferedReader(isr);
String info = null;
while((info=br.readLine())!=null){//循环读取客户端的信息
System.out.println("客户端发送过来的信息" + info);
}
socket.shutdownInput();//关闭输入流
socket.close();
}
}
客户端
Step 1:创建Socket对象,指明需要链接的服务器的地址和端号
Step 2:链接建立后,通过输出流向服务器发送请求信息
Step 3:通过输出流获取服务器响应的信息
Step 4:关闭相关资源
public class Client {
public static void main(String[] args) throws IOException {
acceptServer();
}
//在这里因为只是简单的实现,所以并没有设计到使用多线程,但是在实际中,不可能只有一个客户端,所以,我们应该设计多线程的客户端并发执行。
public static void acceptServer() throws IOException {
//创建socket
Socket socket=new Socket("127.0.0.1",9999);
//获取输出流,向服务器发送信息
OutputStream outputStream= socket.getOutputStream();//字节输出流
PrintWriter printWriter=new PrintWriter(outputStream);//将输出流包装为打印流
//获取客户端的IP地址
InetAddress address=InetAddress.getLocalHost();//获取本机地址
String ip=address.getHostAddress();//将IP地址以字符串形式显示
printWriter.write("客户端:"+ip +"接入服务器");
Scanner aa=new Scanner(System.in);
String client=aa.nextLine();
printWriter.write("我是客户端,我要说:"+client);
printWriter.flush();
socket.shutdownOutput();//关闭输出流
socket.close();//关闭socket
}
}