java echo 服务器_Java实现TCP之Echo客户端和服务端

本文介绍了如何使用Java编写TCP协议的Echo服务器和客户端。服务器端通过多线程处理来自多个客户端的连接,客户端则向服务器发送消息,服务器接收后原样返回。代码包括TCPEchoClient和TCPEchoServer两个类,以及Makefile用于编译和运行。在实际应用中,TCP的聊天室功能可能需要更复杂的线程通信来实现。
摘要由CSDN通过智能技术生成

Java实现TCP之Echo客户端和服务端

代码内容

采用TCP协议编写服务器端代码(端口任意)

编写客户机的代码访问该端口

客户机按行输入

服务器将收到的字符流和接收到的时间输出在服务器console

原样返回给客户机在客户机console显示出来

代码实现

/* TCPEchoClient.java */

import java.io.*;

import java.net.*;

public class TCPEchoClient {

public final static String serverIP = "localhost";

public final static int serverPort = 4347;

public static String userName = null;

public static void main(String[] args) {

Socket client = null;

BufferedReader sin = null;

Writer cout = null;

BufferedReader cin = null;

try {

/* 建立Socket连接 */

client = new Socket(serverIP, serverPort);

/* 从用户键盘读取输入 */

sin = new BufferedReader(new InputStreamReader(System.in));

/* 写入数据到Socket中 */

cout = new OutputStreamWriter(client.getOutputStream());

/* 从Socket读取输入 */

cin = new BufferedReader(new InputStreamReader(client.getInputStream()));

/* 登陆 */

System.out.print("Please login: ");

userName = sin.readLine();

/* 获取用户输入的一行,exit则退出 */

String line;

System.out.print("> ");

line = sin.readLine();

while (!line.equals("exit")) {

/* 将用户输入发送给Server */

cout.write("[" + userName + "]: " + line + "\n");

/* 刷新输出流使Server马上收到用户输入 */

cout.flush();

/* 从Server读入输入并显示 */

System.out.println(cin.readLine());

/* 读取用户下一行输入 */

System.out.print("> ");

line = sin.readLine();

}

} catch (UnknownHostException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

} finally {

/* 安全关闭输入输出和Socket */

try {

cout.close();

cin.close();

client.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

}

/* TCPEchoServer.java */

import java.io.*;

import java.net.*;

import java.util.Date;

import java.lang.System;

import java.lang.Thread;

import java.lang.Runnable;

public class TCPEchoServer {

public final static int serverPort = 4347;

public static int count = 0;

@SuppressWarnings({"resource"})

public static void main(String[] args) {

ServerSocket server = null;

Socket connection = null;

try {

/* 创建一个ServerSocket监听端口 */

server = new ServerSocket(serverPort);

System.out.println("Server start running...");

while (true) {

/* accept()阻塞等待客户返回Socket */

connection = server.accept();

System.out.println("Socket " + count + " established...");

/* 创建一个线程与该用户交互 */

Thread workThread = new Thread(new Handler(connection, count++));

workThread.start();

}

} catch (Exception e) {

e.printStackTrace();

}

}

public static class Handler implements Runnable {

private Socket socket = null;

private int index = -1;

public Handler(Socket _socket, int _index) {

this.socket = _socket;

this.index = _index;

}

public void run() {

BufferedReader cin = null;

Writer cout = null;

try {

/* 从Socket读取输入 */

cin = new BufferedReader(new InputStreamReader(socket.getInputStream()));

/* 写入数据到Socket中 */

cout = new OutputStreamWriter(socket.getOutputStream());

String line;

/* 当Socket连接正常时 */

while (socket.isConnected() && !socket.isClosed()) {

/* 当阻塞成功获取用户输入时 */

line = cin.readLine();

/* 获取当前系统时间 */

Date currentTime = new Date();

String echo = currentTime.toString().split(" ")[3] + " " + line;

/* 打印系统日志记录用户输入 */

System.out.println(echo);

/* 发送数据给用户 */

cout.write(echo + '\n');

/* 刷新输出流使用户马上收到消息 */

cout.flush();

}

} catch (SocketException e) {

// do nothing

} catch (Exception e) {

e.printStackTrace();

} finally {

try {

/* 安全关闭输入输出和Socket */

if (socket != null) {

cout.close();

cin.close();

socket.close();

}

} catch (IOException e) {

e.printStackTrace();

}

System.out.println("Socket " + index + " exit...");

}

}

}

}

/* Makefile */

target:

javac -encoding utf-8 TCPEchoClient.java

javac -encoding utf-8 TCPEchoServer.java

javac -encoding utf-8

run-TCPEchoClient:

java TCPEchoClient

run-TCPEchoServer:

java TCPEchoServer

clean:

rm *.class

运行截图

7ca7722a3aadc216bd060f5b32aeaa94.png

问题解决方案

中文编码问题:在代码使用UTF-8编码并且编译选项添加UTF8参数的话,不需要在代码中声明为UTF8编码,使用了反而会出错,亲测。

面向连接的传输TCP:由于需要面向连接,因此一个服务端需要和多个客户端进行通信,这就需要在服务端使用多线程技术,一个客户端分配一个线程,分别处理不同客户端的通信。

面向无连接的传输UDP:由于不需要连接,也不在意可靠传输,因此当客户端发送了一个数据包之后,若一定时间内没有返回内容,可以认为传输失败,让用户接着输入下一个内容。

关于TCP的聊天室:在客户端中无法体现出一个聊天室的完成功能,但是服务端是体现出来了,如果需要在客户端也有这个体现,需要做线程之间的通信,想想还是太麻烦我就没做了。

还有一点是面向连接的程序,不应该每发送一次就连接一次再断开连接,这样子的通信效率太低,而是应该等到客户端退出后再断开连接,这点已实现。

样例代码下载

传送门:下载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值