使用 java 的简单多线程服务器聊天
simple multi-threaded server chat using java
我正在创建一个 java 处理多客户端的聊天服务器 我将这个简单的代码用于服务器
public class Server extends Thread {
ServerSocket serverSocket = null;
Socket socket = null;
private int unique_id;
ArrayList<Clients> cl;
public Server(int port) {
try {
serverSocket = new ServerSocket(port);
cl = new ArrayList<>();
this.start();
} catch (Exception e){
System.out.println("Error 5");
e.printStackTrace();
}
}
@Override
public void run(){
System.out.println("Server Start");
while (true){
try {
socket = serverSocket.accept();
Clients t = new Clients(socket); // add it to thread
cl.add(t);
t.start();
System.out.println("Connected " + String.valueOf(cl.size())); // printed ok
}catch (Exception e){
System.out.println("Error 4");
e.printStackTrace();
}
}
}
public synchronized void SendToAll(String s){ // this function used by client when one of client socket send a message then server send it to all
System.out.println("Sended is excuted"); // excuted normal each time i send a message from client but not send to all
for (int i = 0; i < cl.size(); i++){
cl.get(i).WriteToSocket(s);
}
}
public static void main(String args[]){
int port = 5002;
Server server = new Server(port); // start server
//server.run(); // start connections wait for it
}
class Clients extends Thread { // class extends thread
public Socket socket = null;
DataInputStream input = null; // read input
DataOutputStream output = null; // read output
public int myid = 0; // unique id for each client
public Clients(Socket soc) {
socket = soc;
try {
input = new DataInputStream(socket.getInputStream());
output = new DataOutputStream(socket.getOutputStream());
myid = ++unique_id;
System.out.println("Client Start Thread"); // printed ok !
} catch (IOException e){
System.out.println("Error 1");
e.printStackTrace();
}
}
public void WriteToSocket(String s) { // used to write a message to this socket
try {
output.write(s.getBytes());
}catch (IOException e){
System.out.println("Error 2");
e.printStackTrace();
}
}
@Override
public void run() { // run thread function wait for messages from clients
while (true){
try {
String s = input.readLine();
if (s.contains("quite")) {
socket.close();
input.close();
output.close();
cl.remove(this);
this.stop();
}
if (!s.isEmpty()) {
SendToAll(s);// when message come and not empty it use server function to send them to all clients
}
}catch (IOException e){
System.out.println("Error 3");
e.printStackTrace();
}
}
}
}
}
当客户端连接服务器接受连接并且客户端线程启动时一切正常
但是问题是当我从客户端发送消息时服务器没有收到我在 java 中也使用 Qt c++ 服务器尝试我的客户端应用程序并且它有效?
那么我在这里做错了什么使服务器无法接收消息?
这是我第一次使用 java
进行网络编程
编辑
我解决了 NullPointerException 问题是当客户端注销时我没有从 ArrayList 中删除他的套接字通过在关闭发送消息之前让客户端解决包含很多,所以当我看到它时,我从数组列表中删除了他的套接字
Another Quetiosn
这里我不知道这条消息是如何发送的
每次客户端发送消息时,SendToAll 函数中的 System.out.println() 都会打印到屏幕上,但为什么消息不会再次发送给所有客户端?
实际上主要的问题是当消息来自一个客户端后,服务器无法将消息发送给数组列表中的所有客户端问题还没有解决,stell found
客户端代码 class
public class ClientSocket extends Thread {
public Socket socket = null;
public DataInputStream input = null;
public DataOutputStream output = null;
MainChat chat = null;
public ClientSocket(String ip, int port,MainChat ch) {
try {
socket = new Socket(ip,port);
input = new DataInputStream(socket.getInputStream());
output = new DataOutputStream(socket.getOutputStream());
chat = ch;
this.start();
}catch (IOException e){
}
}
@Override
public void run() {
while (true){
try {
String s = input.readLine();
if (!s.isEmpty()){
chat.WriteToScreen(s.trim());
}
}catch (IOException e){
}
}
}
public void WriteToSocket(String s) throws IOException{
output.write(s.getBytes());
}
}
编辑
当我在 main 中使用此代码时,SendToAll 函数将消息发送给所有客户端!为什么当我使用 Thread 从客户端 class 使用它时,它没有发送给所有人?
public static void main(String args[]){
int port = 5002;
Server server = new Server(port); // start server
//server.run(); // start connections wait for it
while (true) {
String s = in.next();
server.SendToAll(s + "\n"); // message sended to all client !!
}
}
我解决了问题,很抱歉这是我的错我忘记在 sendToAll 函数中添加 \n 所以这是导致问题的原因所以没有 \n 客户端无法读取该行,因为我在 DataInputStream
中使用了 readLine
无论如何,我尝试另一种方法来读取字节而不是 readLine 我认为它更好,特别是当您收到 UTF-8 char 并且之后从字节更改为 String
问题是 readLine 读取直到找到文件末尾的行终止符。这就是为什么它可以与 QT C++ 中的其他服务器一起使用,但不能与 Java 服务器一起使用。
请看这里:
https://docs.oracle.com/javase/7/docs/api/java/io/DataInput.html#readLine()
https://docs.oracle.com/javase/7/docs/api/java/io/DataInputStream.html#readLine()
请注意,DataInputStream 中的 readLine 已弃用。你应该使用 BufferedReader to read a line (with readLine) as indicated in the DataInputStream link.
因此,将'\n'添加到发送的字符串的末尾即可。
我正在创建一个 java 处理多客户端的聊天服务器 我将这个简单的代码用于服务器
public class Server extends Thread {
ServerSocket serverSocket = null;
Socket socket = null;
private int unique_id;
ArrayList<Clients> cl;
public Server(int port) {
try {
serverSocket = new ServerSocket(port);
cl = new ArrayList<>();
this.start();
} catch (Exception e){
System.out.println("Error 5");
e.printStackTrace();
}
}
@Override
public void run(){
System.out.println("Server Start");
while (true){
try {
socket = serverSocket.accept();
Clients t = new Clients(socket); // add it to thread
cl.add(t);
t.start();
System.out.println("Connected " + String.valueOf(cl.size())); // printed ok
}catch (Exception e){
System.out.println("Error 4");
e.printStackTrace();
}
}
}
public synchronized void SendToAll(String s){ // this function used by client when one of client socket send a message then server send it to all
System.out.println("Sended is excuted"); // excuted normal each time i send a message from client but not send to all
for (int i = 0; i < cl.size(); i++){
cl.get(i).WriteToSocket(s);
}
}
public static void main(String args[]){
int port = 5002;
Server server = new Server(port); // start server
//server.run(); // start connections wait for it
}
class Clients extends Thread { // class extends thread
public Socket socket = null;
DataInputStream input = null; // read input
DataOutputStream output = null; // read output
public int myid = 0; // unique id for each client
public Clients(Socket soc) {
socket = soc;
try {
input = new DataInputStream(socket.getInputStream());
output = new DataOutputStream(socket.getOutputStream());
myid = ++unique_id;
System.out.println("Client Start Thread"); // printed ok !
} catch (IOException e){
System.out.println("Error 1");
e.printStackTrace();
}
}
public void WriteToSocket(String s) { // used to write a message to this socket
try {
output.write(s.getBytes());
}catch (IOException e){
System.out.println("Error 2");
e.printStackTrace();
}
}
@Override
public void run() { // run thread function wait for messages from clients
while (true){
try {
String s = input.readLine();
if (s.contains("quite")) {
socket.close();
input.close();
output.close();
cl.remove(this);
this.stop();
}
if (!s.isEmpty()) {
SendToAll(s);// when message come and not empty it use server function to send them to all clients
}
}catch (IOException e){
System.out.println("Error 3");
e.printStackTrace();
}
}
}
}
}
当客户端连接服务器接受连接并且客户端线程启动时一切正常
但是问题是当我从客户端发送消息时服务器没有收到我在 java 中也使用 Qt c++ 服务器尝试我的客户端应用程序并且它有效?
那么我在这里做错了什么使服务器无法接收消息?
这是我第一次使用 java
进行网络编程
编辑
我解决了 NullPointerException 问题是当客户端注销时我没有从 ArrayList 中删除他的套接字通过在关闭发送消息之前让客户端解决包含很多,所以当我看到它时,我从数组列表中删除了他的套接字
Another Quetiosn
这里我不知道这条消息是如何发送的
每次客户端发送消息时,SendToAll 函数中的 System.out.println() 都会打印到屏幕上,但为什么消息不会再次发送给所有客户端?
实际上主要的问题是当消息来自一个客户端后,服务器无法将消息发送给数组列表中的所有客户端问题还没有解决,stell found
客户端代码 class
public class ClientSocket extends Thread {
public Socket socket = null;
public DataInputStream input = null;
public DataOutputStream output = null;
MainChat chat = null;
public ClientSocket(String ip, int port,MainChat ch) {
try {
socket = new Socket(ip,port);
input = new DataInputStream(socket.getInputStream());
output = new DataOutputStream(socket.getOutputStream());
chat = ch;
this.start();
}catch (IOException e){
}
}
@Override
public void run() {
while (true){
try {
String s = input.readLine();
if (!s.isEmpty()){
chat.WriteToScreen(s.trim());
}
}catch (IOException e){
}
}
}
public void WriteToSocket(String s) throws IOException{
output.write(s.getBytes());
}
}
编辑
当我在 main 中使用此代码时,SendToAll 函数将消息发送给所有客户端!为什么当我使用 Thread 从客户端 class 使用它时,它没有发送给所有人?
public static void main(String args[]){
int port = 5002;
Server server = new Server(port); // start server
//server.run(); // start connections wait for it
while (true) {
String s = in.next();
server.SendToAll(s + "\n"); // message sended to all client !!
}
}
我解决了问题,很抱歉这是我的错我忘记在 sendToAll 函数中添加 \n 所以这是导致问题的原因所以没有 \n 客户端无法读取该行,因为我在 DataInputStream
中使用了 readLine
无论如何,我尝试另一种方法来读取字节而不是 readLine 我认为它更好,特别是当您收到 UTF-8 char 并且之后从字节更改为 String
问题是 readLine 读取直到找到文件末尾的行终止符。这就是为什么它可以与 QT C++ 中的其他服务器一起使用,但不能与 Java 服务器一起使用。 请看这里: https://docs.oracle.com/javase/7/docs/api/java/io/DataInput.html#readLine() https://docs.oracle.com/javase/7/docs/api/java/io/DataInputStream.html#readLine()
请注意,DataInputStream 中的 readLine 已弃用。你应该使用 BufferedReader to read a line (with readLine) as indicated in the DataInputStream link.
因此,将'\n'添加到发送的字符串的末尾即可。