Java通过 Socket 实现 TCP服务端

下面开始对“Java通过Socket实现TCP服务端”的完整攻略进行详细讲解。

概述

在Java中,可以通过Socket来实现TCP的通信。作为服务端,需要启动一个监听线程来接受客户端的连接请求,并创建一个接受处理线程来处理客户端发送的数据。下面将从以下几个方面来讲解如何通过Socket实现TCP服务端:

  1. 启动服务端
  2. 监听客户端连接请求
  3. 处理客户端发送的数据
  4. 关闭服务端

启动服务端

在Java中启动服务端,需要创建一个ServerSocket对象,并设置需要监听的端口号。以下是示例代码:

int port = 8080;
try {
    ServerSocket serverSocket = new ServerSocket(port);
    System.out.println("服务端已启动,监听端口:" + port);
} catch (IOException e) {
    e.printStackTrace();
}

监听客户端连接请求

启动服务端后,需要创建一个线程来监听客户端的连接请求。对于每个连接请求,都需要创建一个新的Socket对象来与客户端进行通信。以下是示例代码:

while (true) {
    try {
        Socket clientSocket = serverSocket.accept();
        System.out.println("客户端连接成功,客户端地址:" + clientSocket.getInetAddress() + ",客户端端口:" + clientSocket.getPort());
        // 处理客户端发送的数据
        // ...
    } catch (IOException e) {
        e.printStackTrace();
    }
}

在循环中调用ServerSocket.accept()方法,等待客户端连接请求。如果客户端发起连接请求,则该方法将返回一个新的Socket对象,程序将创建一个新线程来处理该连接。

处理客户端发送的数据

在接受到客户端连接后,需要通过InputStream读取客户端发送的数据,并通过OutputStream将处理结果返回给客户端。以下是示例代码:

try {
    InputStream inputStream = clientSocket.getInputStream();
    OutputStream outputStream = clientSocket.getOutputStream();
    byte[] buffer = new byte[1024];
    int len;
    while ((len = inputStream.read(buffer)) > 0) {
        String receivedData = new String(buffer, 0, len);
        System.out.println("接收到客户端数据:" + receivedData);
        // 处理客户端发送的数据
        String responseData = "收到您发来的数据:" + receivedData;
        outputStream.write(responseData.getBytes());
        outputStream.flush();
        System.out.println("响应客户端数据:" + responseData);
    }
} catch (IOException e) {
    e.printStackTrace();
} finally {
    try {
        clientSocket.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

在处理数据的过程中,需要通过InputStream读取客户端发送的数据。可以先创建一个byte数组作为缓冲区,通过InputStream.read()方法读取客户端发送的数据。读取到数据之后,可以将byte数组转换为字符串,并进行处理。

处理完客户端发送的数据之后,需要通过OutputStream将处理结果返回给客户端。可以通过OutputStream.write()方法将处理结果转换为byte数组,再通过OutputStream.flush()方法将数据发送给客户端。

处理完客户端数据后,需要关闭与客户端的Socket连接。

关闭服务端

在服务端不需要接受客户端连接请求时,需要关闭ServerSocket对象。以下是示例代码:

try {
    serverSocket.close();
    System.out.println("服务端已关闭");
} catch (IOException e) {
    e.printStackTrace();
}

示例

下面给出两个示例:

示例1

该示例实现了一个简单的文件上传服务器,客户端向服务端上传文件,服务端将文件保存到指定目录中。以下是服务端代码:

int port = 8080;
String savePath = "D:/upload/";
int bufferSize = 1024;
ServerSocket serverSocket = new ServerSocket(port);
System.out.println("服务端已启动,监听端口:" + port);
while (true) {
    try {
        Socket clientSocket = serverSocket.accept();
        System.out.println("客户端连接成功,客户端地址:" + clientSocket.getInetAddress() + ",客户端端口:" + clientSocket.getPort());
        // 处理客户端发送的数据
        InputStream inputStream = clientSocket.getInputStream();
        byte[] buffer = new byte[bufferSize];
        int len;
        String fileName = null;
        int fileLength = 0;
        // 读取文件名
        if ((len = inputStream.read(buffer)) > 0) {
            fileName = new String(buffer, 0, len);
        }
        // 读取文件长度
        if ((len = inputStream.read(buffer)) > 0) {
            fileLength = Integer.parseInt(new String(buffer, 0, len));
        }
        FileOutputStream fileOutputStream = new FileOutputStream(new File(savePath + fileName));
        // 读取文件内容
        int count = 0;
        while ((len = inputStream.read(buffer)) > 0) {
            fileOutputStream.write(buffer, 0, len);
            count += len;
            if (count == fileLength) {
                break;
            }
        }
        fileOutputStream.close();
        // 响应客户端
        OutputStream outputStream = clientSocket.getOutputStream();
        String responseData = "文件上传成功";
        outputStream.write(responseData.getBytes());
        outputStream.flush();
        System.out.println("响应客户端数据:" + responseData);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

以下是客户端代码:

String serverIP = "localhost";
int port = 8080;
String filePath = "D:/test.jpg";
int bufferSize = 1024;
Socket clientSocket = new Socket(serverIP, port);
InputStream inputStream = new FileInputStream(new File(filePath));
OutputStream outputStream = clientSocket.getOutputStream();
byte[] buffer = new byte[bufferSize];
int len;
// 发送文件名
String fileName = new File(filePath).getName();
outputStream.write(fileName.getBytes());
outputStream.flush();
// 发送文件长度
int fileLength = inputStream.available();
String fileLengthStr = String.valueOf(fileLength);
outputStream.write(fileLengthStr.getBytes());
outputStream.flush();
// 发送文件内容
while ((len = inputStream.read(buffer)) > 0) {
    outputStream.write(buffer, 0, len);
    outputStream.flush();
}
// 接收响应
buffer = new byte[bufferSize];
if ((len = clientSocket.getInputStream().read(buffer)) > 0) {
    String responseData = new String(buffer, 0, len);
    System.out.println("接收到服务端响应:" + responseData);
}
inputStream.close();
outputStream.close();
clientSocket.close();

示例2

该示例通过Socket实现了多线程的服务端。以下是服务端代码:

int port = 8080;
ServerSocket serverSocket = new ServerSocket(port);
System.out.println("服务端已启动,监听端口:" + port);
while (true) {
    try {
        Socket clientSocket = serverSocket.accept();
        System.out.println("客户端连接成功,客户端地址:" + clientSocket.getInetAddress() + ",客户端端口:" + clientSocket.getPort());
        new SocketThread(clientSocket).start();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

以下是SocketThread类的代码:

public class SocketThread extends Thread {

    private final Socket clientSocket;

    public SocketThread(Socket clientSocket) {
        this.clientSocket = clientSocket;
    }

    @Override
    public void run() {
        try {
            InputStream inputStream = clientSocket.getInputStream();
            OutputStream outputStream = clientSocket.getOutputStream();
            byte[] buffer = new byte[1024];
            int len;
            while ((len = inputStream.read(buffer)) > 0) {
                String receivedData = new String(buffer, 0, len);
                System.out.println("接收到客户端数据:" + receivedData);
                // 处理客户端发送的数据
                String responseData = "收到您发来的数据:" + receivedData;
                outputStream.write(responseData.getBytes());
                outputStream.flush();
                System.out.println("响应客户端数据:" + responseData);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                clientSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

以上就是用Java通过Socket实现TCP服务端的完整攻略,包括启动服务端、监听客户端连接请求、处理客户端发送的数据和关闭服务端四个方面,并提供了两个示例。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java通过 Socket 实现 TCP服务端 - Python技术站

(0)
上一篇 2023年6月27日
下一篇 2023年6月27日

相关文章

  • 微信小程序子组件给父组件传参

    微信小程序子组件给父组件传参 对于微信小程序开发中的组件化开发,经常会涉及到父子组件之间的数据传递问题。在这篇文章中,我们将会介绍如何在微信小程序中通过子组件向父组件传递参数。 首先,我们需要明确的是,在微信小程序中,子组件不可直接修改父组件的数据。因此,我们需要通过一定的方式来实现数据传递。 方式一:事件传递 通过事件传递的方式,子组件通过 trigger…

    其他 2023年3月28日
    00
  • vue3+Pinia+TypeScript 实现封装轮播图组件

    下面我将详细讲解”vue3+Pinia+TypeScript 实现封装轮播图组件”的完整攻略: 1. 前置知识 在开始之前需要先掌握以下知识: Vue3基础语法 TypeScript基础语法 Pinia要点 2. 创建轮播图组件 创建组件文件 首先需要在项目中创建Carousel组件的.vue和.ts文件,用于定义组件的模板和业务逻辑代码。 引入Pinia …

    other 2023年6月25日
    00
  • 关于c++:二维数组中出现“标量初始化程序中的多余元素”

    在C++中,二维数组的初始化是一个常见的操作。但是,有时候在初始化二维数组时,会出现“标量初始化程序中的多余元素”的错误。这个错误通常是由于初始化列表中的元素数量与数组大小不匹配导致的。下面是解决这个问题的完整攻略。 问题分析 在C++中,二维数组的初始化通常使用以下语法: int arr[2][3] = {{1, 2, 3}, {4, 5, 6}}; 这个…

    other 2023年5月7日
    00
  • 关于java:system.getproperty(”key”)从何处读取

    下面是关于“关于java:system.getproperty(‘key’)从何处读取”的完整攻略: 1. Java System.getProperty() 简介 Java System.getProperty() 是一个用于获取系统属性的方法,它可以获取系统一些基本信息,例如操作系统名称、Java 运行环境版本、用户的主目录等。在 Java 中,可以使用…

    other 2023年5月7日
    00
  • crayon怎么读?

    Crayon的正确发音为 ‘kreɪən’,其中’kreɪ’的发音与单词“gray(灰色)”中的 ‘gray’ 发音相似,而’ən’的发音与单词“on(在……上)”中的 ‘on’ 发音相似。 以下是针对该单词的完整攻略: 标题 如何正确发音Crayon? 正文 分解单词。 首先我们需要将Crayon分解为两个音节kreɪən。这个单词中的“cray”发音类似…

    其他 2023年4月16日
    00
  • C语言详解链式队列与循环队列的实现

    C语言详解链式队列与循环队列的实现 链式队列的实现 链式队列是一种使用链表实现的队列。这种队列没有静态数组的限制,可以动态地添加或删除元素。 链式队列的定义 链式队列可以通过定义一个结构体来表示: typedef struct node{ int data; // 存放队列元素的数据 struct node *next; // 存放下一个元素的地址 }Nod…

    other 2023年6月27日
    00
  • GO实现文件上传操作

    GO是一门高效而又简洁的编程语言,它利用Goroutine实现了轻松高效的并发编程。在GO语言中,文件上传是一个常见的需求。GO语言可以轻松地实现文件的上传操作,本文将为大家详细讲解GO实现文件上传的完整攻略。 简介 上传文件是指将本地文件发送到Web服务器上,因此在GO语言中,我们需要使用HTTP协议发送文件。GO语言提供了一些方法来处理HTTP协议,我们…

    other 2023年6月27日
    00
  • C++结构体用法实例分析

    C++结构体用法实例分析 本文将详细介绍C++结构体的用法,并提供两个实例说明。 结构体 结构体是C++中一种用户自定义的数据类型,可以包含多个不同类型的数据成员。其定义方式如下: struct <结构体名称> { <数据类型> <数据成员1>; <数据类型> <数据成员2>; … <数据…

    other 2023年6月27日
    00
合作推广
合作推广
分享本页
返回顶部