Java网络编程菜鸟进阶:TCP和套接字入门

发表于:2012-1-10 09:35

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:蜀山兆孨龘    来源:51Testing软件测试网采编

  JDK 提供了对 TCP(Transmission Control Protocol,传输控制协议)和 UDP(User Datagram Protocol,用户数据报协议)这两个数据传输协议的支持。本文开始探讨 TCP。

  TCP 基础知识

  在“服务器-客户端”这种架构中,服务器和客户端各自维护一个端点,两个端点需要通过网络进行数据交换。TCP 为这种需求提供了一种可靠的流式连接,流式的意思是传出和收到的数据都是连续的字节,没有对数据量进行大小限制。一个端点由 IP 地址和端口构成(专业术语为“元组 {IP 地址, 端口}”)。这样,一个连接就可以由元组 {本地地址, 本地端口, 远程地址, 远程端口} 来表示。

  连接过程

  在 TCP 编程接口中,端点体现为 TCP 套接字。共有两种 TCP 套接字:主动和被动,“被动”状态也常被称为“侦听”状态。服务器和客户端利用套接字进行连接的过程如下:

  1、服务器创建一个被动套接字,开始循环侦听客户端的连接。

  2、客户端创建一个主动套接字,连接服务器。

  3、服务器接受客户端的连接,并创建一个代表该连接的主动套接字。

  4、服务器和客户端通过步骤 2 和 3 中创建的两个主动套接字进行数据传输。

  下面是连接过程的图解:

  一个简单的 TCP 服务器

  JDK 提供了 ServerSocket 类来代表 TCP 服务器的被动套接字。下面的代码演示了一个简单的 TCP 服务器(多线程阻塞模式),它不断侦听并接受客户端的连接,然后将客户端发送过来的文本按行读取,全文转换为大写后返回给客户端,直到客户端发送文本行 bye:

  1. public class TcpServer implements Runnable {   
  2.     private ServerSocket serverSocket;   
  3.     
  4.     public TcpServer(int port) throws IOException {   
  5.         // 创建绑定到某个端口的 TCP 服务器被动套接字。  
  6.         serverSocket = new ServerSocket(port);   
  7.     }   
  8.     
  9.     @Override 
  10.     public void run() {   
  11.         while (true) {   
  12.             try {   
  13.                 // 以阻塞的方式接受一个客户端连接,返回代表该连接的主动套接字。  
  14.                 Socket socket = serverSocket.accept();   
  15.                 // 在新线程中处理客户端连接。  
  16.                 new Thread(new ClientHandler(socket)).start();   
  17.             } catch (IOException ex) {   
  18.                 ex.printStackTrace();   
  19.             }   
  20.         }   
  21.     }   
  22. }   
  23.     
  24. public class ClientHandler implements Runnable {   
  25.     private Socket socket;   
  26.     
  27.     public ClientHandler(Socket socket) {   
  28.         this.socket = Objects.requireNonNull(socket);   
  29.     }   
  30.     
  31.     @Override 
  32.     public void run() {   
  33.         try (Socket s = socket) {  // 减少代码量的花招……  
  34.             // 包装套接字的输入流以读取客户端发送的文本行。  
  35.             BufferedReader in = new BufferedReader(new InputStreamReader(   
  36.                     s.getInputStream(), StandardCharsets.UTF_8));   
  37.             // 包装套接字的输出流以向客户端发送转换结果。  
  38.             PrintWriter out = new PrintWriter(new OutputStreamWriter(   
  39.                     s.getOutputStream(), StandardCharsets.UTF_8), true);   
  40.     
  41.             String line = null;   
  42.             while ((line = in.readLine()) != null) {   
  43.                 if (line.equals("bye")) {   
  44.                     break;   
  45.                 }   
  46.     
  47.                 // 将转换结果输出给客户端。  
  48.                 out.println(line.toUpperCase(Locale.ENGLISH));   
  49.             }   
  50.         } catch (IOException ex) {   
  51.             ex.printStackTrace();   
  52.         }   
  53.     }   
  54. }

21/212>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号