我怎样才能改进 java 与多个客户的聊天?
How can I improve this java chat with multiple clients?
对于一个学校项目,我必须在 java 中与多个用户聊天。我做到了,它有效,但我认为并不完美。将来我想添加一个 GUI,但在此之前我想更正它。所以我的问题是我该如何改进它?我能做些什么更好?这是我的代码。在客户端,我使用主线程等待用户输入,另一个线程监听服务器等待来自其他客户端的消息。在服务器端,我使用主线程接受来自客户端的新连接请求和管理 N 个客户端的 N 个线程。请帮助我。
客户端:
import java.net.*;
import java.io.*;
class listener implements Runnable{
private Socket connection;
private static boolean running;
listener(Socket connection){
this.connection=connection;
running=true;
}
public void run(){
InputStreamReader in;
BufferedReader sIN;
String msgToRecv;
try{
in=new InputStreamReader(connection.getInputStream());
sIN=new BufferedReader(in);
}
catch(IOException e){
System.out.println(e);
return;
}
while(running){
try{
msgToRecv=sIN.readLine();
}
catch(IOException e){
System.out.println("Connection closed: "+e);
return;
}
System.out.println(msgToRecv);
}
return;
}
public static void stopListening(){
running=false;
return;
}
}
class Client
{
public static void main(String[] args)
{
String ipAddServer="127.0.0.1";
int port=8080;
Socket connection=null;
String msgToSend;
String username;
InputStreamReader input=new InputStreamReader(System.in);
BufferedReader tastiera=new BufferedReader(input);
OutputStream out;
PrintWriter sOUT;
System.out.println("Enter a username");
try{
connection=new Socket(ipAddServer, port);
out=connection.getOutputStream();
sOUT=new PrintWriter(out);
username=tastiera.readLine();
}
catch(IOException e){
System.out.println(e);
return;
}
System.out.println("User: "+username);
System.out.println("Chat Joined");
Thread t=new Thread(new listener(connection));
t.start();
do{
try{
msgToSend=tastiera.readLine();
}
catch(IOException e){
System.out.println(e);
return;
}
sOUT.println(username+": "+msgToSend);
sOUT.flush();
}while(!msgToSend.equals("EXIT"));
listener.stopListening();
try
{
connection.close();
}
catch(IOException e)
{
System.out.println(e);
}
return;
}
}
服务器端:
import java.net.*;
import java.io.*;
import java.util.ArrayList;
class clientHandler implements Runnable{
private ServerSocket sSocket;
private Socket connection;
private ArrayList<Socket> sockets;
public clientHandler(ServerSocket sSocket, Socket connection, ArrayList<Socket> sockets) {
this.sSocket=sSocket;
this.connection=connection;
this.sockets=sockets;
}
public void run(){
InputStreamReader in, input;
BufferedReader sIN, tastiera;
OutputStream out;
PrintWriter sOUT;
String msgToRecv;
try{
out=connection.getOutputStream();
sOUT=new PrintWriter(out);
in=new InputStreamReader(connection.getInputStream());
sIN=new BufferedReader(in);
}
catch(Exception e){
System.out.println(e);
return;
}
sockets.add(connection);
do{
try{
msgToRecv=sIN.readLine();
}
catch(IOException e){
System.out.println(e);
return;
}
for(int i=0;i<sockets.size();++i){
Socket temp=sockets.get(i);
if(!connection.equals(temp)&&!msgToRecv.equals("null")){
OutputStream tmpOut;
PrintWriter tmpSOUT;
try{
tmpOut=temp.getOutputStream();
tmpSOUT=new PrintWriter(tmpOut);
}
catch(IOException e){
System.out.println(e);
return;
}
tmpSOUT.println(msgToRecv);
tmpSOUT.flush();
}
}
}while(msgToRecv!=null);
sockets.remove(sOUT);
return;
}
}
class Server
{
public static void main(String[] args)
{
int port=8080;
ServerSocket sSocket;
ArrayList<Socket> sockets=new ArrayList<Socket>();
Thread t;
try{
sSocket=new ServerSocket(port);
}
catch(IOException e){
System.out.println(e);
return;
}
while(true){
try{
t=new Thread(new clientHandler(sSocket, sSocket.accept(), sockets));
}
catch(IOException e){
System.out.println(e);
return;
}
t.start();
}
}
}
当你开发聊天服务器(最好是软实时服务器)时,有一些重要的事情:
1.管理资源
2。低延迟
3。可扩展性
4.耐用度
5.可用性
6.存储数据(聊天、文件和...)
当您为学校开发此服务器时,您可以跳过第 2、3、4 和 5 部分。
第 1 部分:在任何程序中管理资源都非常重要,在聊天服务器中也是如此。你有 N 个客户端,你需要 N 个线程?不,这不是一个好主意,有一个很好的方法可以用 none-blocking-socket 来处理它,这将帮助您在一个线程中处理许多连接。记住不要在服务器上创建很多线程,也不要浪费 CPU 和内存。有时您必须更好地了解如何重用分配的缓冲区,而不是创建导致 CPU 和内存资源浪费的新缓冲区。
第 6 部分:将数据存储在每秒接收许多请求的聊天服务器中需要管理。有时需要让数据批处理,然后将它们推送到数据存储。它比一个一个地推送数据要快得多,当然数据库和它们的驱动程序库会在它们的层中处理这些事情,但它太重要了,不能在你的应用程序层内部进行批处理。聊天服务器中有很多不错的数据库,但最好的是 Apache Cassandra.
注意 : 它只是与开发聊天服务器无关,但最好使您的代码更易于理解和编程 事件驱动(UserConnect、UserDisconnect、MessageRecived 和...)。一个好的做法是通过定义接口(例如:AbstractServer、AbstractDataBase 和...)来创建程序逻辑抽象,然后为您的程序创建一个可运行的部分,该部分直接使用该接口,独立于该接口的功能工作方式,然后实现这个接口。使用此模型,您可以将您的程序分成更小的部分,并使实施程序更容易。
对于一个学校项目,我必须在 java 中与多个用户聊天。我做到了,它有效,但我认为并不完美。将来我想添加一个 GUI,但在此之前我想更正它。所以我的问题是我该如何改进它?我能做些什么更好?这是我的代码。在客户端,我使用主线程等待用户输入,另一个线程监听服务器等待来自其他客户端的消息。在服务器端,我使用主线程接受来自客户端的新连接请求和管理 N 个客户端的 N 个线程。请帮助我。
客户端:
import java.net.*;
import java.io.*;
class listener implements Runnable{
private Socket connection;
private static boolean running;
listener(Socket connection){
this.connection=connection;
running=true;
}
public void run(){
InputStreamReader in;
BufferedReader sIN;
String msgToRecv;
try{
in=new InputStreamReader(connection.getInputStream());
sIN=new BufferedReader(in);
}
catch(IOException e){
System.out.println(e);
return;
}
while(running){
try{
msgToRecv=sIN.readLine();
}
catch(IOException e){
System.out.println("Connection closed: "+e);
return;
}
System.out.println(msgToRecv);
}
return;
}
public static void stopListening(){
running=false;
return;
}
}
class Client
{
public static void main(String[] args)
{
String ipAddServer="127.0.0.1";
int port=8080;
Socket connection=null;
String msgToSend;
String username;
InputStreamReader input=new InputStreamReader(System.in);
BufferedReader tastiera=new BufferedReader(input);
OutputStream out;
PrintWriter sOUT;
System.out.println("Enter a username");
try{
connection=new Socket(ipAddServer, port);
out=connection.getOutputStream();
sOUT=new PrintWriter(out);
username=tastiera.readLine();
}
catch(IOException e){
System.out.println(e);
return;
}
System.out.println("User: "+username);
System.out.println("Chat Joined");
Thread t=new Thread(new listener(connection));
t.start();
do{
try{
msgToSend=tastiera.readLine();
}
catch(IOException e){
System.out.println(e);
return;
}
sOUT.println(username+": "+msgToSend);
sOUT.flush();
}while(!msgToSend.equals("EXIT"));
listener.stopListening();
try
{
connection.close();
}
catch(IOException e)
{
System.out.println(e);
}
return;
}
}
服务器端:
import java.net.*;
import java.io.*;
import java.util.ArrayList;
class clientHandler implements Runnable{
private ServerSocket sSocket;
private Socket connection;
private ArrayList<Socket> sockets;
public clientHandler(ServerSocket sSocket, Socket connection, ArrayList<Socket> sockets) {
this.sSocket=sSocket;
this.connection=connection;
this.sockets=sockets;
}
public void run(){
InputStreamReader in, input;
BufferedReader sIN, tastiera;
OutputStream out;
PrintWriter sOUT;
String msgToRecv;
try{
out=connection.getOutputStream();
sOUT=new PrintWriter(out);
in=new InputStreamReader(connection.getInputStream());
sIN=new BufferedReader(in);
}
catch(Exception e){
System.out.println(e);
return;
}
sockets.add(connection);
do{
try{
msgToRecv=sIN.readLine();
}
catch(IOException e){
System.out.println(e);
return;
}
for(int i=0;i<sockets.size();++i){
Socket temp=sockets.get(i);
if(!connection.equals(temp)&&!msgToRecv.equals("null")){
OutputStream tmpOut;
PrintWriter tmpSOUT;
try{
tmpOut=temp.getOutputStream();
tmpSOUT=new PrintWriter(tmpOut);
}
catch(IOException e){
System.out.println(e);
return;
}
tmpSOUT.println(msgToRecv);
tmpSOUT.flush();
}
}
}while(msgToRecv!=null);
sockets.remove(sOUT);
return;
}
}
class Server
{
public static void main(String[] args)
{
int port=8080;
ServerSocket sSocket;
ArrayList<Socket> sockets=new ArrayList<Socket>();
Thread t;
try{
sSocket=new ServerSocket(port);
}
catch(IOException e){
System.out.println(e);
return;
}
while(true){
try{
t=new Thread(new clientHandler(sSocket, sSocket.accept(), sockets));
}
catch(IOException e){
System.out.println(e);
return;
}
t.start();
}
}
}
当你开发聊天服务器(最好是软实时服务器)时,有一些重要的事情:
1.管理资源
2。低延迟
3。可扩展性
4.耐用度
5.可用性
6.存储数据(聊天、文件和...)
当您为学校开发此服务器时,您可以跳过第 2、3、4 和 5 部分。
第 1 部分:在任何程序中管理资源都非常重要,在聊天服务器中也是如此。你有 N 个客户端,你需要 N 个线程?不,这不是一个好主意,有一个很好的方法可以用 none-blocking-socket 来处理它,这将帮助您在一个线程中处理许多连接。记住不要在服务器上创建很多线程,也不要浪费 CPU 和内存。有时您必须更好地了解如何重用分配的缓冲区,而不是创建导致 CPU 和内存资源浪费的新缓冲区。
第 6 部分:将数据存储在每秒接收许多请求的聊天服务器中需要管理。有时需要让数据批处理,然后将它们推送到数据存储。它比一个一个地推送数据要快得多,当然数据库和它们的驱动程序库会在它们的层中处理这些事情,但它太重要了,不能在你的应用程序层内部进行批处理。聊天服务器中有很多不错的数据库,但最好的是 Apache Cassandra.
注意 : 它只是与开发聊天服务器无关,但最好使您的代码更易于理解和编程 事件驱动(UserConnect、UserDisconnect、MessageRecived 和...)。一个好的做法是通过定义接口(例如:AbstractServer、AbstractDataBase 和...)来创建程序逻辑抽象,然后为您的程序创建一个可运行的部分,该部分直接使用该接口,独立于该接口的功能工作方式,然后实现这个接口。使用此模型,您可以将您的程序分成更小的部分,并使实施程序更容易。