先来看个最简 DEMO(双向通信):
![]()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| public class SocketServer { public static void main(String[] args) throws Exception { ServerSocket server = new ServerSocket(8080); Socket socket = server.accept();
InputStream inputStream = socket.getInputStream(); byte[] bytes = new byte[1024]; int len; StringBuilder sb = new StringBuilder(); while ((len = inputStream.read(bytes)) != -1) { sb.append(new String(bytes, 0, len,"UTF-8")); } System.out.println("Received: " + sb); OutputStream outputStream = socket.getOutputStream(); outputStream.write("hello client".getBytes("UTF-8")); outputStream.flush();
inputStream.close(); outputStream.close(); socket.close(); server.close(); } }
public class SocketClient { public static void main(String args[]) throws Exception { Socket socket = new Socket("127.0.0.1", 8080); OutputStream outputStream = socket.getOutputStream(); String message="hello server"; outputStream.write(message.getBytes("UTF-8")); socket.shutdownOutput(); InputStream inputStream = socket.getInputStream(); byte[] bytes = new byte[1024]; int len; StringBuilder sb = new StringBuilder(); while ((len = inputStream.read(bytes)) != -1) { sb.append(new String(bytes, 0, len,"UTF-8")); } System.out.println("Received: " + sb);
inputStream.close(); outputStream.close(); socket.close(); } }
|
原理简介
随着服务器进程的运行,客户端进程可以向服务器发起传输控制协议。这是在客户端程序中通过创建套接字对象来完成的。当客户端创建其套接字对象时,它指定了服务器进程的地址,即服务器的IP地址和进程的端口号。一旦创建套接字对象,客户端中的TCP发起三次握手,并与服务器建立传输控制协议。三次握手对客户端和服务器程序完全透明。
![]()
在三次握手期间,客户端进程敲响服务器进程的欢迎门。当服务器“听到”敲响时,它会创建一个专用于该特定客户端的新门(即一个新套接字)。在我们下面的示例中,欢迎门是一个ServerSocket对象,我们称之为welcomSocket。当客户端敲响这扇门时,程序调用welcomSocket的接受()方法,该方法为客户端创建一个新门。在握手阶段结束时,客户端的套接字和服务器的新套接字之间存在一个传输控制协议。从今以后,我们将新套接字称为服务器的“连接套接字”。
![]()
从应用程序的角度来看,传输控制协议是客户端套接字和服务器连接套接字之间的直接虚拟管道。客户端进程可以将任意字节发送到其套接字中;TCP保证服务器进程将接收(通过连接套接字)发送顺序中的每个字节。此外,正如人们可以进出同一扇门一样,客户端进程也可以从其套接字接收字节,服务器进程也可以将字节发送到其连接套接字中。
从流中解析消息
从上面的介绍可以看出 TCP 可以被抽象的视为一条字节流,TCP 协议保证了数据的顺序和exactly once。但是由于数据是流的方式传递,如何从流中获取一条消息就是用户进程需要关心的,下面将介绍几种方案。
关闭流