TCP流套接字编程

这篇具有很好参考价值的文章主要介绍了TCP流套接字编程。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

TCP流套接字编程,JavaEE,tcp/ip,单片机,网络协议,网络编程

前言

前面我们学习了使用 UDP 数据报实现套接字编程,因为 UDP 和 TCP 存在一些差异,所以在实现 TCP 流套接字编程的时候也会出现一些不同的做法,这篇文章我将为大家分享如何使用 TCP 流实现套接字编程。

TCP 和 UDP 的特点对比

要想实现 TCP 流的套接字编程就需要先知道 TCP 和 UDP 的区别。

  1. TCP 是有连接的,UDP 是无连接的。
  2. TCP 是可靠传输,UDP 是不可靠传输。
  3. TCP 是面向字节流,UDP 是面向数据报。
  4. TCP 和 UDP 都是全双工的。

这里实现 TCP 流套接字编程与 UDP 数据报套接字编程的区别则主要体现在 TCP 有连接,UDP 无连接;TCP 面向字节流,UDP 面向数据报。

TcpEchoServer 服务端实现

1. 创建 ServerSocket 类实现通信双方建立连接

要想实现 TCP 通信,首先需要通信双方建立连接。在 Java 中,TCP 双方建立连接依靠 ServerSocket 接口,ServerSocket 底层类似一个阻塞队列,当客户端和服务端建立连接之后,ServerSocket 会通过内核将这些建立好的连接给依次存储下来,当双方需要进行通信的时候服务器就会将这个连接从内核中取出来,然后进行通信。

public class TcpEchoServer {
    ServerSocket serverSocket = null;
    
    public TcpEchoServer(int port) throws IOException {
    	//服务端需要指定端口号
        serverSocket = new ServerSocket(port);
    }
}

2. 取出建立的连接实现双方通信

通过 accept() 方法可以取出建立的连接进行双方的通信。

public void start() throws IOException {
	System.out.println("服务端启动");
    while (true) {
        Socket clientSocket = serverSocket.accept();
        //进行通信
        processConnection(clientSocket);
    }
}

3. 服务端业务逻辑实现

TCP 是面向字节流的传输,不像 UDP 依靠数据报传输,所以在这里需要用到前面文件操作的 InputStreamOutputStream 来实现请求的读取和响应的发送了。

public void processConnection(Socket clientSocket) {
	//提示客户端上线
    System.out.printf("[%s %d] 客户端线\n",clientSocket.getInetAddress(),
            clientSocket.getPort());
    try (InputStream inputStream = clientSocket.getInputStream();
         OutputStream outputStream = clientSocket.getOutputStream()) {
            
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

读取字节数据的时候会显得比较麻烦,所以可以使用 Scanner 来简化读取过程。
scanner.next() 方法读取到空白符(空格、回车、制表符)结束,这正好与我们客户端输入请求的时候以空白符结束对应。

Scanner scanner = new Scanner(inputStream);
while (true) {
	if (!scanner.hasNext()) {
        System.out.printf("[%s %d] 客户端下线",clientSocket.getInetAddress(),
        clientSocket.getPort());
        break;
    }
    String request = scanner.next();
}

process(String request) 方法实现对请求数据的处理。

String response = process(request);

public String process(String request) {
    return request;
}

当服务端接收到 process() 方法返回的数据之后,就需要将处理的数据返回给服务端,因为同样是面向字节流,所以需要依靠 OutputStream 类来将数据传输给服务端,但是字节流操作较麻烦,所以可以使用 PrintWriter 类封装一下 OutputStream 类来简化操作。

PrintWriter printWriter = new PrintWriter(outputStream);
printWriter.println(response);
printWriter.flush();
//打印出服务端日志
System.out.printf("[%s %d] req=%s res=%s\n",clientSocket.getInetAddress(),
                clientSocket.getPort(),request,response);

关闭资源

在 TCP 流实现套接字编程的时候,如果不关闭资源的话就会出现资源泄露的问题,那么为什么会出现资源泄露呢?当服务器和新的客户端实现双方通信的时候就是调用 serverSocket.accept() 方法创建出新的 Socket 资源,而且这个 Socket 资源并不是一直贯穿服务端程序始终的,所以在这里就需要及时关闭资源,防止发生资源泄露的问题。

但是呢,我们不是使用了 try-with-resources 模型吗,当这个模型当中的代码执行完成了之后不是会自动调用里面的对象的 close 方法吗?是的,这里没问题,但是我们在这个模型中创建的是 InputStream 对象和 OutputStream 对象,程序结束的时候关闭的是流对象,而 Socket 对象并没有关闭,所以就还需要我们呢手动关闭这个 Socket 资源。

我们这里使用的是 finally 代码块来关闭资源,防止中间代码出现异常而导致资源没有成功关闭。

finally {
    clientSocket.close();
}

服务端整体代码

package netWork;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

public class TcpEchoServer {
    ServerSocket serverSocket = null;

    public TcpEchoServer(int port) throws IOException {
        //服务端需要指定端口号
        serverSocket = new ServerSocket(port);
    }
    
    public void start() throws IOException {
        System.out.println("服务端启动");
        while (true) {
            Socket clientSocket = serverSocket.accept();
            processConnection(clientSocket);
        }
    }

    public void processConnection(Socket clientSocket) throws IOException {
        System.out.printf("[%s %d] 客户端上线\n",clientSocket.getInetAddress(),
                clientSocket.getPort());
        try (InputStream inputStream = clientSocket.getInputStream();
             OutputStream outputStream = clientSocket.getOutputStream()) {
            Scanner scanner = new Scanner(inputStream);
            PrintWriter printWriter = new PrintWriter(outputStream);
            while (true) {
                if (!scanner.hasNext()) {
                    System.out.printf("[%s %d] 客户端下线",clientSocket.getInetAddress(),
                            clientSocket.getPort());
                    break;
                }
                String request = scanner.next();
                String response = process(request);
                printWriter.println(response);
                printWriter.flush();
                System.out.printf("[%s %d] req=%s res=%s\n",clientSocket.getInetAddress(),
                clientSocket.getPort(),request,response);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            clientSocket.close();
        }
    }

    public String process(String request) {
        return request;
    }

    public static void main(String[] args) throws IOException {
        TcpEchoServer tcpEchoServer = new TcpEchoServer( 9906);
        tcpEchoServer.start();
    }
}


TcpEchoClient 客户端实现

1. 创建出 Socket 对象来与服务端实现通信

客户端实现与服务端的通信依赖于 Socket 接口。

public class TcpEchoClient {
    Socket socket = null;
    public TcpEchoClient(String serverIp, int serverPort) throws IOException {
        socket = new Socket(serverIp,serverPort);
    }
}

虽然 TCP 通信,双方会保存对方的信息,但是我们在客户端代码中还是需要指定出 目的 IP 和 目的端口

2. 实现客户端的主要逻辑

提示用户输入请求数据。

public void run() {
    Scanner scanner = new Scanner(System.in);
    try (InputStream inputStream = socket.getInputStream();
         OutputStream outputStream = socket.getOutputStream()) {
        Scanner netWorkScanner = new Scanner(inputStream);
        while (true) {
            String request = scanner.next();
        }
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
 }

将请求的数据通过 OutputStream 传输。

PrintWriter printWriter = new PrintWriter(outputStream);
printWriter.println(request);
printWriter.flush();

使用 InputStream 读取服务端传回的数据。

Scanner netWorkScanner = new Scanner(inputStream);
String response = netWorkScanner.next();
System.out.println(response);

服务端整体代码

package netWork;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;

public class TcpEchoClient {
    private Socket socket = null;

    public TcpEchoClient(String serverIp, int serverPort) throws IOException {
        // 需要在创建 Socket 的同时, 和服务器 "建立连接", 此时就得告诉 Socket 服务器在哪里~~
        // 具体建立连接的细节, 不需要咱们代码手动干预. 是内核自动负责的.
        // 当我们 new 这个对象的时候, 操作系统内核, 就开始进行 三次握手 具体细节, 完成建立连接的过程了.
        socket = new Socket(serverIp, serverPort);
    }

    public void start() {
        // tcp 的客户端行为和 udp 的客户端差不多.
        // 都是:
        // 3. 从服务器读取响应.
        // 4. 把响应显示到界面上.
        Scanner scanner = new Scanner(System.in);
        try (InputStream inputStream = socket.getInputStream();
             OutputStream outputStream = socket.getOutputStream()) {
            PrintWriter writer = new PrintWriter(outputStream);
            Scanner scannerNetwork = new Scanner(inputStream);
            while (true) {
                // 1. 从控制台读取用户输入的内容
                System.out.print("-> ");
                String request = scanner.next();
                // 2. 把字符串作为请求, 发送给服务器
                //    这里使用 println, 是为了让请求后面带上换行.
                //    也就是和服务器读取请求, scanner.next 呼应
                writer.println(request);
                writer.flush();
                // 3. 读取服务器返回的响应.
                String response = scannerNetwork.next();
                // 4. 在界面上显示内容了.
                System.out.println(response);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws IOException {
        TcpEchoClient client = new TcpEchoClient("192.168.144.1", 9090);
        client.start();
    }
}

功能实现

TCP流套接字编程,JavaEE,tcp/ip,单片机,网络协议,网络编程
TCP流套接字编程,JavaEE,tcp/ip,单片机,网络协议,网络编程

多个客户端访问服务器

既然是网络编程,那肯定离不开多个客户端同时访问一个服务器的情况,如果我们要想使用多个客户端同时访问同一个服务器能行吗?

在 IDEA 中如何实现同一个代码两个进程呢?

TCP流套接字编程,JavaEE,tcp/ip,单片机,网络协议,网络编程
TCP流套接字编程,JavaEE,tcp/ip,单片机,网络协议,网络编程
TCP流套接字编程,JavaEE,tcp/ip,单片机,网络协议,网络编程

TCP流套接字编程,JavaEE,tcp/ip,单片机,网络协议,网络编程
TCP流套接字编程,JavaEE,tcp/ip,单片机,网络协议,网络编程
TCP流套接字编程,JavaEE,tcp/ip,单片机,网络协议,网络编程
TCP流套接字编程,JavaEE,tcp/ip,单片机,网络协议,网络编程
TCP流套接字编程,JavaEE,tcp/ip,单片机,网络协议,网络编程

TCP流套接字编程,JavaEE,tcp/ip,单片机,网络协议,网络编程
当多个客户端同时访问这个服务器的时候,我们可以发现:这个功能并没有真正的实现。那么为什么这个代码不能实现多个客户端同时访问同一个服务器的情况呢?

通过观察服务器端的代码,可以发现:其实这里是有两个 while 循环的,第一个循环是用来取得和多个客户端的连接的,但是为什么这里没有取得和我们的第二个客户端的连接呢?这里第一个客户端在和服务端进行通信的时候,是处在第二个 while 循环当中的,并且这里第一个客户端并没有与服务器断开连接,也就是说,当前服务器还处于第二个 while 循环中等待第一个客户端发送请求,所以当第二个客户端想要和服务器进行通信的时候就不能到达 serverSocket.accept() 方法与服务器进行通信。那么如何解决这个问题呢?

这就需要用到我们前面学习的多线程的知识了,创建多个线程进行 processConnection() 方法,这样就可以使的另一个客户端想要和服务器进行通信的时候就可以在另一个线程中得到和服务器的连接。

public void start() throws IOException {
    System.out.println("服务端启动");
    while (true) {
        Socket clientSocket = serverSocket.accept();
        Thread t = new Thread(() -> {
            try {
                processConnection(clientSocket);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        });
        t.start();
    }
}

TCP流套接字编程,JavaEE,tcp/ip,单片机,网络协议,网络编程
TCP流套接字编程,JavaEE,tcp/ip,单片机,网络协议,网络编程
TCP流套接字编程,JavaEE,tcp/ip,单片机,网络协议,网络编程

但是这样频繁的创建和销毁线程也会消耗较多的资源,所以这里可以做出优化:使用线程池,虽然这里线程池可以优化,但是优化的不多。

public void start() throws IOException {
    System.out.println("服务端启动");
    ExecutorService service = Executors.newCachedThreadPool();
    while (true) {
        Socket clientSocket = serverSocket.accept();
        service.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    processConnection(clientSocket);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        });
    }
 }

其实这里处理多个客户端同一时间访问同一个服务器的最好方法就是 IO 多路复用 / IO 多路转接

IO多路复用是一种同步IO模型,它允许在单个进程/线程内同时处理多个IO请求。具体来说,一个进程/线程可以监视多个文件句柄,一旦某个文件句柄就绪,就能够通知应用程序进行相应的读写操作。如果没有文件句柄就绪,应用程序将被阻塞,并交出CPU。
这种模型允许多个请求共享同一个进程/线程,使得在处理大量请求时,可以更有效地利用系统资源。如果每个请求都使用独立的进程/线程来处理,那么系统需要创建和管理大量的进程/线程,这将消耗大量的系统资源。而使用IO多路复用技术,可以复用一个或几个线程来处理多个TCP连接,从而大大减少了系统开销。
IO多路复用技术的出现主要是为了解决阻塞IO的问题。在操作系统中,最初只有BIO模式,即阻塞IO。当一个请求被处理时,如果该请求需要等待IO操作完成(例如读写操作),则该进程/线程将被阻塞,直到IO操作完成。这会导致系统资源的浪费,尤其是在需要处理大量请求的情况下。
IO多路复用技术的引入解决了这个问题。通过监视多个文件句柄,一个进程/线程可以在同一时间处理多个IO请求,从而提高了系统的效率。当一个文件句柄就绪时,该进程/线程可以立即进行相应的读写操作,而不需要等待其他请求完成。这种方式可以有效地减少系统资源的浪费,并提高系统的吞吐量。
IO多路复用技术被广泛应用在网络编程中,特别是服务器端编程。由于服务器需要同时处理来自大量客户端的请求,因此使用IO多路复用技术可以提高服务器的性能和响应速度。例如,Nginx服务器就使用了IO多路复用技术来处理大量的客户端连接。

这里具体怎么解决我这里及不过多叙述了,大家有兴趣可以去学习学习。

优化后的服务端代码

package netWork1;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class TcpEchoServer {
    private ServerSocket serverSocket = null;

    public TcpEchoServer(int port) throws IOException {
        serverSocket = new ServerSocket(port);
    }

    public void start() throws IOException {
        System.out.println("服务器启动!");
        ExecutorService service = Executors.newCachedThreadPool();
        while (true) {
            // 通过 accept 方法, 把内核中已经建立好的连接拿到应用程序中.
            // 建立连接的细节流程都是内核自动完成的. 应用程序只需要 "捡现成" 的.
            Socket clientSocket = serverSocket.accept();
            // 此处不应该直接调用 processConnection, 会导致服务器不能处理多个客户端.
            // 创建新的线程来调用更合理的做法.
            // 这种做法可行, 不够好
//            Thread t = new Thread(() -> {
//                processConnection(clientSocket);
//            });
//            t.start();

            // 更好一点的办法, 是使用线程池.
            service.submit(new Runnable() {
                @Override
                public void run() {
                    processConnection(clientSocket);
                }
            });
        }
    }

    // 通过这个方法, 来处理当前的连接.
    public void processConnection(Socket clientSocket) {
        // 进入方法, 先打印一个日志, 表示当前有客户端连上了.
        System.out.printf("[%s:%d] 客户端上线!\n", clientSocket.getInetAddress(), clientSocket.getPort());
        // 接下来进行数据的交互.
        try (InputStream inputStream = clientSocket.getInputStream();
             OutputStream outputStream = clientSocket.getOutputStream()) {
            // 使用 try ( ) 方式, 避免后续用完了流对象, 忘记关闭.
            // 由于客户端发来的数据, 可能是 "多条数据", 针对多条数据, 就循环的处理.
            while (true) {
                Scanner scanner = new Scanner(inputStream);
                if (!scanner.hasNext()) {
                    // 连接断开了. 此时循环就应该结束
                    System.out.printf("[%s:%d] 客户端下线!\n", clientSocket.getInetAddress(), clientSocket.getPort());
                    break;
                }
                // 1. 读取请求并解析. 此处就以 next 来作为读取请求的方式. next 的规则是, 读到 "空白符" 就返回.
                String request = scanner.next();
                // 2. 根据请求, 计算响应.
                String response = process(request);
                // 3. 把响应写回到客户端.
                //    可以把 String 转成字节数组, 写入到 OutputStream
                //    也可以使用 PrintWriter 把 OutputStream 包裹一下, 来写入字符串.
                PrintWriter printWriter = new PrintWriter(outputStream);
                //    此处的 println 不是打印到控制台了, 而是写入到 outputStream 对应的流对象中, 也就是写入到 clientSocket 里面.
                //    自然这个数据也就通过网络发送出去了. (发给当前这个连接的另外一端)
                //    此处使用 println 带有 \n 也是为了后续 客户端这边 可以使用 scanner.next 来读取数据.
                printWriter.println(response);
                //    此处还要记得有个操作, 刷新缓冲区. 如果没有刷新操作, 可能数据仍然是在内存中, 没有被写入网卡.
                printWriter.flush();
                // 4. 打印一下这次请求交互过程的内容
                System.out.printf("[%s:%d] req=%s, resp=%s\n", clientSocket.getInetAddress(), clientSocket.getPort(),
                        request, response);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                // 在这个地方, 进行 clientSocket 的关闭.
                // processConnection 就是在处理一个连接. 这个方法执行完毕, 这个连接也就处理完了.
                clientSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public String process(String request) {
        // 此处也是写的回显服务器. 响应和请求是一样的.
        return request;
    }

    public static void main(String[] args) throws IOException {
        TcpEchoServer server = new TcpEchoServer(9906);
        server.start();
    }
}

根据回显服务器实现一个简单的字典功能

这个功能服务器的业务逻辑相比于简单的回显就稍复杂了一点,但是也没有复杂很多,只是需要更改一下服务端的 process 方法,在这个方法中使用 Map 存储几个单词的翻译就好了。

package netWork;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class TcpDictServer extends TcpEchoServer {

    Map<String, String> dict = new HashMap<>();
    public TcpDictServer(int port) throws IOException {
        super(port);
        dict.put("cat","小猫");
        dict.put("dog","小狗");
        dict.put("bird","小鸟");
        dict.put("pig","小猪");
    }

    @Override
    public String process(String request) {
        return dict.getOrDefault(request,"您查找的单词在该词典中不存在");
    }

    public static void main(String[] args) throws IOException {
        TcpDictServer tcpDictServer = new TcpDictServer(9906);
        tcpDictServer.start();
    }
}

TCP流套接字编程,JavaEE,tcp/ip,单片机,网络协议,网络编程
TCP流套接字编程,JavaEE,tcp/ip,单片机,网络协议,网络编程文章来源地址https://www.toymoban.com/news/detail-712702.html

到了这里,关于TCP流套接字编程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • TCP/IP网络编程(二) 套接字协议及其数据传输特性

    关于协议 如果相隔比较远的两人进行通话,必须先决定通话方式,如果一方选择电话,另一方也必须选择电话,否则接受不到消息。 总之,协议就是为了完成数据交换而定好的约定。 创建套接字 协议族 通过socket函数的第一个参数传递套接字中使用的协议分类信息,此协议

    2024年02月10日
    浏览(62)
  • 【Linux】socket 编程(socket套接字介绍、字节序、socket地址、IP地址转换函数、套接字函数、TCP通信实现)

    橙色 所谓套接字,就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。 一个套接字就是网络上进程通信的一端,提供了应用层进程利用网络协议交换数据的机制。从所处的地位来讲,套接字上联应用进程,下联网络协议栈,是应用程序通过网络协议进程通

    2024年02月09日
    浏览(56)
  • TCP/IP网络编程 第十五章:套接字和标准I/O

    标准I/O函数的两个优点 将标准I/O函数用于数据通信并非难事。但仅掌握函数使用方法并没有太大意义,至少应该 了解这些函数具有的优点。下面列出的是标准I/O函数的两大优点: □标准I/O函数具有良好的移植性(Portability) □标准I/O函数可以利用缓冲提高性能。 关于移植性无需

    2024年02月16日
    浏览(54)
  • TCP套接字编程详解

    目录 为什么socket编程又叫套接字编程? TCP服务端 初始化套接字库——WSAStarup 创建套接字——socket 绑定到本机 ——bind 开始监听 ——listen 连接客户端请求——accept 发送与接收数据 ——send/recv 完整代码 TCP客户端  初始化套接字库——WSAStarup  创建套接字  连接服务器——

    2024年01月19日
    浏览(36)
  • TCP流套接字编程

    前面我们学习了使用 UDP 数据报实现套接字编程,因为 UDP 和 TCP 存在一些差异,所以在实现 TCP 流套接字编程的时候也会出现一些不同的做法,这篇文章我将为大家分享如何使用 TCP 流实现套接字编程。 要想实现 TCP 流的套接字编程就需要先知道 TCP 和 UDP 的区别。 TCP 是有连接

    2024年02月08日
    浏览(45)
  • tcp连接+套接字编程

    TCP的连接是需要四个要素确定唯一一个连接: (源IP,源端口号)+ (目地IP,目的端口号) 所以TCP首部预留了两个16位作为端口号的存储,而IP地址由上一层IP协议负责传递 源端口号和目地端口各占16位两个字节,也就是端口的范围是2^16=65535 另外1024以下是 系统 保留的端口,

    2024年02月09日
    浏览(35)
  • 【JaveEE】网络编程之TCP套接字、UDP套接字

    目录 1.网络编程的基本概念 1.1为什么需要网络编程  1.2服务端与用户端 1.3网络编程五元组  1.4套接字的概念 2.UDP套接字编程 2.1UDP套接字的特点  2.2UDP套接字API 2.2.1DatagramSocket类 2.2.2DatagramPacket类  2.2.3基于UDP的回显程序 2.2.4基于UDP的单词查询  3.TCP套接字编程 3.1TCP套接字的特

    2023年04月13日
    浏览(169)
  • 【Linux】TCP套接字编程

    目录 前言 UDP服务器的完善 线程的封装 结构定义 接口实现 环形队列 结构定义 接口实现 加锁 信号量的申请与释放 入队与出队 整体组装  初始化与析构 信息接收线程 消息发送线程 TCP套接字 创建套接字 listen accept 收发操作 客户端的编写 进一步完善 多进程 多线程 总结 上篇

    2024年02月05日
    浏览(39)
  • 网络编程套接字( TCP )

    目录 1、实现一个TCP网络程序(单进程版)         1.1、服务端serverTcp.cc文件                  服务端创建套接字                  服务端绑定                  服务端监听                  服务端获取连接                  服务

    2024年01月17日
    浏览(270)
  • 网络编程【TCP流套接字编程】

    目录 TCP流套接字编程 1.ServerSocket API 2.Socket API 3.TCP中的长短连接 4.回显程序(短连接) 5.服务器和客户端它们的交互过程 6.运行结果及修改代码   ❗❗两个核心: ServerSocket     Socket 1.ServerSocket API ✨ ServerSocket 是创建 TCP服务端Socket的API ServerSocket 构造方法: ServerSocket 方法 :

    2023年04月12日
    浏览(149)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包