Java编程实现多线程TCP服务器完整实例

Java编程实现多线程TCP服务器完整实例

简介

本文将通过Java代码实现一个多线程的TCP服务器,包含完整的代码以供参考。该服务器能够同时服务多个客户端,每个客户端都在独立的线程中运行。本文将介绍如何实现TCP Socket编程,以及如何使用Java多线程进行并发编程。

实现目标

  1. 实现一个多线程TCP服务器,支持多客户端同时连接。
  2. 服务器能够接受客户端连接,并读取并输出客户端发送的消息。
  3. 服务器能够向客户端发送消息,并关闭连接。

代码实现

以下是实现该目标的Java代码,我们对其进行分析:

import java.io.*;
import java.net.*;

public class MultithreadedTCPServer {
    public static void main(String[] args) throws IOException {
        //创建一个ServerSocket监听端口
        int portNumber = 5000;
        try (ServerSocket serverSocket = new ServerSocket(portNumber)) {
            System.out.println("服务器启动,监听端口号: " + portNumber);
            //循环等待客户端连接
            while (true) {
                //客户端连接成功,创建新的Socket来处理客户端请求
                new ClientThread(serverSocket.accept()).start();
            }
        } catch (IOException e) {
            System.err.println("无法监听端口 " + portNumber);
            System.exit(-1);
        }
    }
}

//处理客户端请求的线程类
class ClientThread extends Thread {
    private Socket socket;
    private PrintWriter out;
    private BufferedReader in;

    public ClientThread(Socket socket) {
        super("ClientThread");
        this.socket = socket;
    }

    public void run() {
        try {
            System.out.println("客户端连接成功。地址:" + socket.getRemoteSocketAddress());

            //获取Socket的输入输出流,用于向客户端发送和接收消息
            out = new PrintWriter(socket.getOutputStream(), true);
            in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

            String inputLine;
            while ((inputLine = in.readLine()) != null) {
                //客户端发送了"Bye"时,关闭连接
                if (inputLine.equals("Bye")) {
                    break;
                }
                //向客户端发送消息
                out.println("服务器响应:" + inputLine);
            }

            //关闭连接
            out.close();
            in.close();
            socket.close();
            System.out.println("客户端断开连接。");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

代码实现分析

程序入口

程序入口使用了Java的main方法,其创建了一个ServerSocket并循环等待客户端的连接。

int portNumber = 5000;
try (ServerSocket serverSocket = new ServerSocket(portNumber)) {
    System.out.println("服务器启动,监听端口号: " + portNumber);
    //循环等待客户端连接
    while (true) {
        //客户端连接成功,创建新的Socket来处理客户端请求
        new ClientThread(serverSocket.accept()).start();
    }
} catch (IOException e) {
    System.err.println("无法监听端口 " + portNumber);
    System.exit(-1);
}

其创建一个ServerSocket并绑定在5000端口,表示该服务器将会监听5000端口连接请求。当客户端连接时,主线程将创建一个新的ClientThread线程,并传入连接的Socket作为参数,然后启动该线程。

客户端线程

当客户端连接时,程序将通过一个ClientThread对象来处理客户端请求。该线程需要完成以下任务:

  1. 获取Socket的输入输出流,用于向客户端发送和接收消息。
  2. 读取客户端发送的消息,并向客户端发送响应消息。
  3. 关闭连接。
class ClientThread extends Thread {
    private Socket socket;
    private PrintWriter out;
    private BufferedReader in;

    public ClientThread(Socket socket) {
        super("ClientThread");
        this.socket = socket;
    }

    public void run() {
        try {
            System.out.println("客户端连接成功。地址:" + socket.getRemoteSocketAddress());

            //获取Socket的输入输出流,用于向客户端发送和接收消息
            out = new PrintWriter(socket.getOutputStream(), true);
            in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

            String inputLine;
            while ((inputLine = in.readLine()) != null) {
                //客户端发送了"Bye"时,关闭连接
                if (inputLine.equals("Bye")) {
                    break;
                }
                //向客户端发送消息
                out.println("服务器响应:" + inputLine);
            }

            //关闭连接
            out.close();
            in.close();
            socket.close();
            System.out.println("客户端断开连接。");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

该线程包含了一个私有成员变量Socket,一个PrintWriter对象用于向客户端发送消息,一个BufferedReader对象用于接收客户端的消息。

当客户端连接服务器时,线程的run方法会被执行。在该方法中,首先获取了Socket的输入输出流,用于向客户端发送和接收消息。接着,它会读取客户端发送的消息,并向客户端发送响应消息。当客户端发送了"Bye"时,该线程将关闭连接。

示例

示例1

现在我们可以启动服务器,这可以通过执行MultithreadedTCPServer类的main方法来实现。当服务器开始监听端口时,我们可以启动多个客户端,这通过执行以下客户端代码和使用telnet命令行工具来实现:

import java.io.*;
import java.net.*;

public class TCPClient {
    public static void main(String[] args) throws IOException {
        String hostName = args[0];
        int portNumber = Integer.parseInt(args[1]);

        try (
            Socket socket = new Socket(hostName, portNumber);
            PrintWriter out =
                new PrintWriter(socket.getOutputStream(), true);
            BufferedReader in =
                new BufferedReader(
                    new InputStreamReader(socket.getInputStream()));
            BufferedReader stdIn =
                new BufferedReader(
                    new InputStreamReader(System.in))
        ) {
            String userInput;
            while ((userInput = stdIn.readLine()) != null) {
                out.println(userInput);
                System.out.println("服务器响应: " + in.readLine());
                if (userInput.equals("Bye"))
                    break;
            }
        } catch (UnknownHostException e) {
            System.err.println("无法确定主机: " + hostName);
            System.exit(1);
        } catch (IOException e) {
            System.err.println("无法连接到主机: " + hostName);
            System.exit(1);
        }
    }
}

执行代码java TCPClient localhost 5000可以启动一个客户端并连接到之前启动的服务器。这将打开一个输入流,可以在其中输入消息并将其发送到服务器。服务器会处理这些请求,然后返回响应消息。

示例2

我们可以使用telnet命令来手动连接到之前启动的服务器。在终端输入命令telnet localhost 5000 就能连接到服务器。输入消息并按Enter键发送,服务器将会打印出消息并返回响应消息。当要断开连接时,输入"Bye"即可关闭TCP连接。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java编程实现多线程TCP服务器完整实例 - Python技术站

(0)
上一篇 2023年5月19日
下一篇 2023年5月19日

相关文章

  • java实现日历窗口小程序

    Java实现日历窗口小程序攻略 1. 实现思路 要实现一个日历窗口小程序,可以考虑以下几个步骤: 创建一个Swing界面,显示当前日期以及日历窗口。 在日历窗口中显示当前月份的日历。 提供按钮或其他交互方式,让用户可以切换月份,也可以选择某一天进行其他操作。 2. 示例1:显示当前月份的日历 下面是一个简单的实现示例,可以通过一个二维数组表示一个月份的日历:…

    Java 2023年5月20日
    00
  • Android中ArrayList和数组相互转换

    下面我就来详细讲解一下“Android中ArrayList和数组相互转换”的完整攻略,包含以下内容: 将数组转换成ArrayList 将ArrayList转换成数组 示例说明:数组转ArrayList 示例说明:ArrayList转数组 将数组转换成ArrayList 如果我们需要使用ArrayList来操作数组,那么就需要将数组转换成ArrayList。下…

    Java 2023年5月26日
    00
  • Spring Boot+AngularJS+BootStrap实现进度条示例代码

    Spring Boot+AngularJS+BootStrap实现进度条示例代码 在本文中,我们将详细讲解如何使用Spring Boot、AngularJS和BootStrap实现进度条示例代码。我们将介绍两个不同的示例,以说明如何使用这些技术来实现进度条。 示例一:使用AngularJS和BootStrap实现进度条 在这个示例中,我们将使用Angular…

    Java 2023年5月18日
    00
  • Spring Boot thymeleaf模板引擎的使用详解

    感谢你对Spring Boot和Thymeleaf模板引擎的关注。下面是Spring Boot Thymeleaf模板引擎的使用详解攻略: 1. Thymeleaf简介 Thymeleaf是一个现代化的服务器端Java模板引擎,可以将模板渲染成HTML、XML、JavaScript等格式,并提供模板缓存机制,允许HTML页面的热部署。 2. Spring B…

    Java 2023年6月15日
    00
  • @RequestBody注解Ajax post json List集合数据请求400/415的处理

    首先介绍一下问题的背景,前端使用Ajax技术向后端发送一个POST请求,请求的数据是JSON格式的List集合数据,后端使用Spring MVC框架,利用注解@RequestBody将这个JSON数据映射到后端的Java对象中。但是在处理过程中,出现了400或者415的错误码,这是因为后端无法正确解析请求的JSON数据。那么如何处理这个问题呢?接下来我们来一…

    Java 2023年5月26日
    00
  • Java 判断实体对象及所有属性是否为空的操作

    Java 判断实体对象及所有属性是否为空的操作是日常开发中经常遇到的问题之一,可以用来对数据进行合法性校验。下面将详细介绍如何实现该操作的完整攻略。 判断实体对象是否为空 判断实体对象是否为空可以通过对实体对象本身进行判断的方法实现。我们可以使用 Java 中的 == 或 null 进行判断。 示例: public boolean isObjectNull(…

    Java 2023年5月26日
    00
  • 全面解析Spring Security 内置 Filter

    全面解析Spring Security 内置 Filter 什么是Spring Security Spring Security 是一个完全基于 Spring Framework 的企业应用系统安全性管理框架,提供了诸如身份认证、授权、攻击防范等企业安全所需的基本功能,并且提供了丰富的扩展点,可以根据需求进行二次开发。 Spring Security 内置 …

    Java 2023年5月20日
    00
  • MyBatis-Plus使用ActiveRecord(AR)实现CRUD

    下面是关于“MyBatis-Plus使用ActiveRecord(AR)实现CRUD”的完整攻略: 什么是MyBatis-Plus的ActiveRecord(AR) MyBatis-Plus是一个MyBatis的优秀增强工具,比MyBatis更加强大、方便、强大、灵活,其AR模式是一种ORM思想,使得你可以通过链式调用方法完成CRUD操作,减少了编写重复的S…

    Java 2023年5月26日
    00
合作推广
合作推广
分享本页
返回顶部