欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

java TCP/IP实现简单的多人聊天功能

程序员文章站 2024-03-22 18:12:58
...
原文地址为:java TCP/IP实现简单的多人聊天功能

TCP/IP是可靠的网络协议,数据的传输需要服务端和客户端之间三次“握手”,比较适合文本等一些可靠性要求高的数据传输,但是它的效率较UDP低。下面通过一张图来简要说明使用 ServerSocket 创建 TCP 服务器端和使用Sock创建客户端通信的流程:

java TCP/IP实现简单的多人聊天功能

这只是实现了单个服务端与客户端的通讯,要想实现与多个客户端的通讯,要在服务端的发送信息线程里把信息转发给各个客户端,在服务端里循环监听客户端的连接,每当有一个客户端连接则把该客户端放进一个集合里面(转发信息时用),然后为该客户端新建一个接收线程和一个发送线程。


具体实现代码:

Server端

package project20150806;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Scanner;

//发送信息线程
class SendThreat implements Runnable {
Socket socket;
//在这里使用PrintWriter流来向客户端发送信息,也可以用其它流
PrintWriter pWriter;
//接收来自主线程的客户端集合
private ArrayList<Socket> socketList;

//从键盘输入获取信息
Scanner scanner = new Scanner(System.in);

public SendThreat(Socket socket,ArrayList<Socket> socketList) {
super();
this.socket = socket;
this.socketList=socketList;
try {
//接收socket的字节输出流,用OutputStreamWriter把字节输出流转化为字符流,再传给PrintWriter
pWriter = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

@Override
public void run() {

while (true) {
//获取从键盘输入的信息
String strMsg =socket.getInetAddress().getHostAddress()+":"+ scanner.nextLine();
if (strMsg == "b") {
break;
}

//把服务器收到的信息转发给各个客户端
for (Socket clientSock : socketList) {
PrintWriter pWriter;
try {
//获取socket的输出流,用来向客户端发送信息
pWriter = new PrintWriter(clientSock.getOutputStream());
//输出信息给客户端
pWriter.println(strMsg);
//刷新输出流
pWriter.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

// pWriter.close();
}
//pWriter.println(strMsg);
//pWriter.flush();
//pWriter.close();
// System.out.println(strMsg);
}

}
}

//接收信息线程
class ReceiveThreat implements Runnable {
Socket socket;
BufferedReader bReader;
private ArrayList<Socket> socketList;

public ReceiveThreat(Socket socket, ArrayList<Socket> socketList) {
super();
this.socket = socket;
this.socketList = socketList;
try {
//获取socket的输入流
bReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));

} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

@Override
public void run() {
while (true) {

try {
String strMsg = bReader.readLine();
System.out.println(strMsg);

for (Socket clientSock : socketList) {
PrintWriter pWriter = new PrintWriter(clientSock.getOutputStream());
pWriter.println(strMsg);
pWriter.flush();
// pWriter.close();
}

} catch (IOException e) {
// TODO Auto-generated catch block
ChatServer.socketList.remove(socket);
}
}
}
}

public class ChatServer {

//定义一个集合用来存放 监听到的客户端socket
public static ArrayList<Socket> socketList = new ArrayList<>();

public static void main(String[] args) {
// TODO Auto-generated method stub
ServerSocket serverSocket = null;

try {
//新建一个服务端ServerSocket,锁定端口号为30000,端口号建议锁定大一点的
serverSocket = new ServerSocket(30000);
System.out.println("等待客户端连接...");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
while (true) {
Socket socket = null;
while (true) {
try {
//监听客户端的连接
socket = serverSocket.accept();
//加入集合
socketList.add(socket);
System.out.println("客户端 " + socket.getInetAddress().getHostAddress() + "连接成功!");

// showHello(socket);
//为该客户端分别开启一个发送信息线程和接收信息线程
new Thread(new SendThreat(socket,socketList)).start();
new Thread(new ReceiveThreat(socket, socketList)).start();

} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}

}


客户端:

package project20150806;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;

//发送信息线程
class SendClientThreat implements Runnable {
Socket socket;
PrintWriter pWriter;
Scanner scanner;

public SendClientThreat(Socket socket) {
super();
this.socket = socket;
this.scanner = new Scanner(System.in);
try {
pWriter = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

@Override
public void run() {

while (true) {
String strMsg =socket.getInetAddress().getHostAddress()+":"+ scanner.nextLine();
pWriter.println(strMsg);
pWriter.flush();

//System.out.println(strMsg);
}

}
}

//接收信息线程
class ReceiveClientThreat implements Runnable {
Socket socket;
BufferedReader bReader;

public ReceiveClientThreat(Socket socket) {
super();
this.socket = socket;
try {
bReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

@Override
public void run() {
try {

while (true) {
String strMsg = bReader.readLine();
System.out.println(strMsg);
}

} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}
}

public class ChatClient {

private static Socket socket;

public static void main(String[] args) {
//服务端的IP
String IPAdress="192.168.1.199";
//创建一个客户端socket,指定服务端的IP和端口号
try {
socket = new Socket(IPAdress, 30000);
System.out.println("连接主机成功! ");

new Thread(new ReceiveClientThreat(socket)).start();
new Thread(new SendClientThreat(socket)).start();

} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}


}

}


这样就可以实现简单聊天功能了。把从键盘获取的信息换成从文件获取的流,还可以实现文件传输功能。

如有不足之处请多多指教,谢谢!




转载请注明本文地址:java TCP/IP实现简单的多人聊天功能