• Java Socket编程(3)初识TCP Socket


      Java为TCP协议提供了两个类,分别在客户端编程和服务器端编程中使用它们。在应用程序开始通信之前,需要先创建一个连接,由客户端程序发起;而服务器端的程序需要一直监听着主机的特定端口号,等待客户端的连接。在客户端中我们只需要使用Socket实例,而服务端要同时处理ServerSocket实例和Socket实例;二者并且都使用OutputStreamInpuStream来发送和接收数据。

       学习一种知识最好的方式就是使用它,通过前面的笔记,我们已经知道如何获取主机的地址信息,现在我们通过一个简单的程序来初步学习传输层使用了TCP协议的Socket编程。

    1.TCP服务器端

      在Socket编程中,服务器端远比客户端要复杂得多。服务器端的工作就是建立一个通信终端,被动的等待客户端的连接。下面这个服务器端程序的示例的作用是:监听从控制台输入获取的端口号,并且将客户端发送过来的消息,再发送回去。

     1 import java.net.*;
    2 import java.text.MessageFormat;
    3 import java.io.*;
    4
    5 public class TCPEchoServer {
    6
    7 private static final int BUFSIZE = 32;
    8
    9 /**
    10 * @param args
    11   */
    12 public static void main(String[] args) throws IOException {
    13 // TODO Auto-generated method stub
    14      // 从控制台获取需要监听的端口号
    15 if (args.length != 1)
    16 throw new IllegalArgumentException("Parameter(s):<Port>");
    17 // 获取端口号
    18 int servPort = Integer.parseInt(args[0]);
    19 // 实例化一个ServerSocket对象实例
    20 ServerSocket servSocket = new ServerSocket(servPort);
    21 System.out.println(MessageFormat.format("开始启动监听,端口号:{0}", args[0]));
    22
    23 // 初始接收数据的总字节数
    24 int recvMsgSize;
    25 // 接收数据的缓冲区
    26 byte[] receiveBuf = new byte[BUFSIZE];
    27
    28 // 循环迭代,监听端口号,处理新的连接请求
    29 while (true) {
    30 // 阻塞等待,每接收到一个请求就创建一个新的连接实例
    31 Socket clntSocket = servSocket.accept();
    32 // 获取连接的客户端的 SocketAddress
    33 SocketAddress clientAddress = clntSocket.getRemoteSocketAddress();
    34 // 打印输出连接客户端地址信息
    35 System.out.println("Handling client at" + clientAddress);
    36 // 从客户端接收数据的对象
    37 InputStream in = clntSocket.getInputStream();
    38 // 向客户端发送数据的对象
    39 OutputStream out = clntSocket.getOutputStream();
    40 // 读取客户端发送的数据后,再发送到客户端
    41 while ((recvMsgSize = in.read(receiveBuf)) != -1) {
    42 out.write(receiveBuf, 0, recvMsgSize);
    43 }
    44 // 客户端关闭连接时,关闭连接
    45 System.out.println(" 客户端关闭连接");
    46 clntSocket.close();
    47 }
    48
    49 }
    50
    51 }

    2.TCP客户端

      在Socket编程中,首先客户端需要向服务器端发送,然后被动的等待服务器端的响应。下面的示例中:我们向服务器端发送信息,等待服务器端发送的消息,并打印显示出来。 

     1 import java.io.*;
    2 import java.net.Socket;
    3 import java.net.SocketException;
    4
    5 public class TCPEchoClient {
    6
    7 /**
    8 * @param args
    9 * @throws IOException
    10    */
    11 public static void main(String[] args) throws IOException {
    12 // TODO Auto-generated method stub
    13      // 判断从控制台接受的参数是否正确
    14 if ((args.length < 2) || (args.length > 3))
    15 throw new IllegalArgumentException(
    16 "Parameter(s):<Server><Word>[<Port>]]");
    17 // 获取服务器地址
    18 String server = args[0];
    19 // 获取需要发送的信息
    20 byte[] data = args[1].getBytes();
    21 // 如果有三个从参数那么就获取发送信息的端口号,默认端口号为8099
    22 int servPort = (args.length == 3) ? Integer.parseInt(args[2]) : 8099;
    23 // 根据服务器地址和端口号实例化一个Socket实例
    24 Socket socket = new Socket(server, servPort);
    25 System.out.println("Connected to server...sending echo string");
    26 // 返回此套接字的输入流,即从服务器接受的数据对象
    27 InputStream in = socket.getInputStream();
    28 // 返回此套接字的输出流,即向服务器发送的数据对象
    29 OutputStream out = socket.getOutputStream();
    30 // 向服务器发送从控制台接收的数据
    31 out.write(data);
    32 // 接收数据的计数器,将写入数据的初始偏移量
    33 int totalBytesRcvd = 0;
    34 // 初始化接收数据的总字节数
    35 int bytesRcvd;
    36 while (totalBytesRcvd < data.length) {
    37 // 服务器关闭连接,则返回 -1,read方法返回接收数据的总字节数
    38 if ((bytesRcvd = in.read(data, totalBytesRcvd, data.length
    39 - totalBytesRcvd)) == -1)
    40 throw new SocketException("与服务器的连接已关闭");
    41 totalBytesRcvd += bytesRcvd;
    42 }
    43 // 打印服务器发送来的数据
    44 System.out.println("Received:" + new String(data));
    45 // 关闭连接
    46 socket.close();
    47
    48 }
    49
    50 }

    首先运行服务器端,监听8099端口:

    接着运行客户端程序,并且向服务器端发送消息:

    再次查看我们的服务器端控制台,我们可以看到前面客户端连接的地址信息:

    参考资料:《TCP/IP Socket in Java》 

    作者:晴天猪

    出处:http://www.cnblogs.com/IPrograming 

    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

  • 相关阅读:
    [LeetCode 1029] Two City Scheduling
    POJ 2342 Anniversary party (树形DP入门)
    Nowcoder 106 C.Professional Manager(统计并查集的个数)
    2018 GDCPC 省赛总结
    CF 977 F. Consecutive Subsequence
    Uva 12325 Zombie's Treasure Chest (贪心,分类讨论)
    Poj 2337 Catenyms(有向图DFS求欧拉通路)
    POJ 1236 Network of Schools (强连通分量缩点求度数)
    POJ 1144 Network (求割点)
    POJ 3310 Caterpillar(图的度的判定)
  • 原文地址:https://www.cnblogs.com/IPrograming/p/Java_Socket_3.html
Copyright © 2020-2023  润新知