我想在一个简单的多线程客户端 - 服务器应用程序中实现的是服务器对连接进行计数,当它达到一定数量时,假设为2,它将为每个客户端创建一个线程(所以2个连接意味着2个线程)负责从客户端读取消息并将消息广播到所有其他客户端。以下是我在多线程客户端 - 服务器示例中所做的修改:
SERVER:
import java.io.DataInputStream;
import java.io.PrintStream;
import java.io.IOException;
import java.net.Socket;
import java.net.ServerSocket;
/*
* A chat server that delivers public and private messages.
*/
public class Server_X_Client {
// The server socket.
private static ServerSocket serverSocket = null;
// The client socket.
private static Socket clientSocket = null;
// This chat server can accept up to maxClientsCount clients' connections.
private static final int numOfClients = 2;
private static final clientThread[] threads = new clientThread[numOfClients];
private static final Socket[] sockets = new Socket [numOfClients];
public static void main(String args[]) throws InterruptedException {
// The default port number.
int portNumber = 2222;
int count=0;
/*
* Open a server socket on the portNumber (default 2222). Note that we can
* not choose a port less than 1023 if we are not privileged users (root).
*/
try {
serverSocket = new ServerSocket(portNumber);
} catch (IOException e) {
System.out.println(e);
}
/*
* Create a client socket for each connection and pass it to a new client
* thread.
*/
while (true) {
try {
clientSocket = serverSocket.accept();
int i = 0;
for (i = 0; i < numOfClients; i++) {
if (sockets[i] == null) {
PrintStream os = new PrintStream(clientSocket.getOutputStream());
DataInputStream in = new DataInputStream (clientSocket.getInputStream());
os.println("Enter your name: ");
String name = in.readLine().trim();
os.println("Enter server password: ");
String psw = in.readLine().trim();
if(psw.equals("Pelin")){
os.println("Password is correct+ "+ i+" pls wait..");
sockets[i] = clientSocket;
}else{
os.println("Password is wrong..");
}
break;
}
}
if (i == numOfClients-1) {
for (int j=0;j<numOfClients;j++){
if(threads[j]==null){
(threads[j] = new clientThread(sockets[j], threads)).start();
//threads[j].join();
}
}
}
} catch (IOException e) {
System.out.println(e);
}
}
}
}
/*
* The chat client thread. This client thread opens the input and the output
* streams for a particular client, ask the client's name, informs all the
* clients connected to the server about the fact that a new client has joined
* the chat room, and as long as it receive data, echos that data back to all
* other clients. When a client leaves the chat room this thread informs also
* all the clients about that and terminates.
*/
class clientThread extends Thread {
private DataInputStream is = null;
private PrintStream os = null;
private Socket clientSocket = null;
private clientThread[] threads;
private int maxClientsCount;
public clientThread(Socket clientSocket, clientThread[] threads) {
this.clientSocket = clientSocket;
this.threads = threads;
maxClientsCount = threads.length;
}
public void run() {
int maxClientsCount = this.maxClientsCount;
clientThread[] threads = this.threads;
try {
/*
* Create input and output streams for this client.
*/
is = new DataInputStream(clientSocket.getInputStream());
os = new PrintStream(clientSocket.getOutputStream());
for (int i = 0; i < maxClientsCount; i++) {
if (threads[i] != null && threads[i] != this) {
threads[i].os.println("READY!!);
}
}
while (true) {
String line = is.readLine();
if (line.startsWith("/quit")) {
break;
}
for (int i = 0; i < maxClientsCount; i++) {
if (threads[i] != null) {
threads[i].os.println("Someone:" + line);
}
}
}
for (int i = 0; i < maxClientsCount; i++) {
if (threads[i] != null && threads[i] != this) {
threads[i].os.println("*** The user " +"XXX"
+ " is leaving the chat room !!! ***");
}
}
os.println("*** Bye "+" ***");
/*
* Clean up. Set the current thread variable to null so that a new client
* could be accepted by the server.
*/
for (int i = 0; i < maxClientsCount; i++) {
if (threads[i] == this) {
threads[i] = null;
}
}
/*
* Close the output stream, close the input stream, close the socket.
*/
is.close();
os.close();
clientSocket.close();
} catch (IOException e) {
}
}
}
客户端:
import java.io.DataInputStream;
import java.io.PrintStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
public class NetworkClient implements Runnable {
// The client socket
private static Socket clientSocket = null;
// The output stream
private static PrintStream os = null;
// The input stream
private static DataInputStream is = null;
private static BufferedReader inputLine = null;
private static boolean closed = false;
public static void main(String[] args) {
// The default port.
int portNumber = 2222;
// The default host.
String host = "localhost";
Scanner sc = new Scanner(System.in);
System.out.println("Connecting to " + host + " on port " + portNumber);
/*
* Open a socket on a given host and port. Open input and output
* streams.
*/
try {
clientSocket = new Socket(host, portNumber);
inputLine = new BufferedReader(new InputStreamReader(System.in));
os = new PrintStream(clientSocket.getOutputStream());
is = new DataInputStream(clientSocket.getInputStream());
} catch (UnknownHostException e) {
System.err.println("Don't know about host " + host);
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to the host " + host);
}
/*
* If everything has been initialized then we want to write some data to
* the socket we have opened a connection to on the port portNumber.
*/
if (clientSocket != null && os != null && is != null) {
try {
/* Create a thread to read from the server. */
new Thread(new NetworkClient()).start();
while (!closed) {
os.println(inputLine.readLine().trim());
}
/*
* Close the output stream, close the input stream, close the
* socket.
*/
os.close();
is.close();
clientSocket.close();
} catch (IOException e) {
System.err.println("IOException: " + e);
}
}
}
/*
* Create a thread to read from the server. (non-Javadoc)
*
* @see java.lang.Runnable#run()
*/
public void run() {
/*
* Keep on reading from the socket till we receive "Bye" from the
* server. Once we received that then we want to break.
*/
String responseLine;
try {
while ((responseLine = is.readLine()) != null) {
System.out.println(responseLine);
if (responseLine.indexOf("bye") != -1)
break;
}
closed = true;
} catch (IOException e) {
System.err.println("IOException: " + e);
}
}
}
服务器端当前存在的错误是Thread-Null指针异常;在clientThread类中,当服务器尝试通过写“READY!”来通知所有其他客户端时信息。好像有同步问题。虽然我在输出流上写之前检查thread [i]是否为null,但它会通过此检查,当它尝试编写线程[i] .os.println(“READY !!)时,会发生错误。感谢任何帮助。