LandryBean 2019-12-10
一、TCP/IP协议通信原理
使用TCP套接字编程可以实现基于TCP/IP协议的面向连接的通信,它分为服务器端和客户端两部分,其主要实现过程如下图所示:
(1)连接建立:服务器调用socket()、 bind()、 listen()完成初始化后,调用accept()阻塞等待,处于监听端口的状态,客户端调用socket()初始化后,调用connect()发出SYN段并阻塞等待服务器应答,服务器应答一个SYN-ACK段,客户端收到后从connect()返回,同时应答一个ACK段,服务器收到后从accept()返回。
(2)数据传输:建立连接后, TCP协议提供全双工的通信服务,但是一般的客户端/服务器程序的流程是由客户端主动发起请求,服务器被动处理请求,一问一答的方式。因此,服务器从accept()返回后立刻调用read(),读socket就像读管道一样,如果没有数据到达就阻塞等待,这时客户端调用write()发送请求给服务器,服务器收到后从read()返回,对客户端的请求进行处理,在此期间客户端调用read()阻塞等待服务器的应答,服务器调用write()将处理结果发回给客户端,再次调用read()阻塞等待下一条请求,客户端收到后从read()返回,发送下一条请求,如此循环下去。
(3)关闭连接:如果客户端没有更多的请求了,就调用close()关闭连接,就像写端关闭的管道一样,服务器的read()返回0,这样服务器就知道客户端关闭了连接,也调用close()关闭连接。注意,任何一方调用close()后,连接的两个传输方向都关闭,不能再发送数据了。如果一方调用shutdown()则连接处于半关闭状态,仍可接收对方发来的数据。
二、JavaSocket
Socket和ServerSocket类库位于java.net包中。ServerSocket用于服务器端,Socket是建立网络连接时使用的。在连接成功时,应用程序两端都会产生一个Socket实例,操作这个实例,完成所需的会话。对于一个网络连接来说,套接字是平等的,并没有差别,不因为在服务器端或在客户端而产生不同级别。不管是Socket还是ServerSocket它们的工作都是通过SocketImpl类及其子类完成的。抽象类SocketImpl是实现套接字的所有类的通用超类。创建客户端和服务器套接字都可以使用它。
socket()调用过程如下:
三、基于java的socket编程
客户端:
import java.io.BufferedReader; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.net.Socket; import java.net.UnknownHostException; /* * 简易在线聊天程序客户端 */ public class client { public static void main(String[]args) throws UnknownHostException, IOException{ System.out.println("---client---"); //连接建立,使用Socket创建客户端,这里要注意端口号要跟本地其它已经写过的网络程序相区分开 Socket client =new Socket("localhost",666); //客户端发送消息 BufferedReader console=new BufferedReader(new InputStreamReader(System.in)); String msg = console.readLine(); DataOutputStream dos= new DataOutputStream(client.getOutputStream()); dos.writeUTF(msg); dos.flush(); //接收消息 DataInputStream dis = new DataInputStream(client.getInputStream()); msg = dis.readUTF(); System.out.println(msg); //释放资源 dos.close(); dis.close(); client.close(); } }
服务端:
import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.net.UnknownHostException; /* * 简易在线聊天程序服务端 */ public class server { public static void main(String[]args) throws UnknownHostException,IOException{ System.out.println("---server---"); //指定端口 使用ServerSocket创建服务器 ServerSocket server = new ServerSocket(666); //阻塞式等待连接 Socket client = server.accept(); System.out.println("一个客户端连接建立"); //接收消息 DataInputStream dis = new DataInputStream(client.getInputStream()); String msg = dis.readUTF(); System.out.println("client say:"+msg); //返回消息 DataOutputStream dos= new DataOutputStream(client.getOutputStream()); dos.writeUTF(msg); //释放资源 dos.flush(); dos.close(); dis.close(); client.close(); } }
实验结果: