A client connects to the Server, the server sends to the client 1 message and the client must wait for another message. While client waiting in while(true) loop it loads the CPU to 50%. I try to do this as simple I can to learn how it works.
P.S. All catch() already hiden to minimize code here.
Client:
public class SocketClient
{
String host;
int port;
static Socket connection;
BufferedReader bfr;
public SocketClient(String host, int port)
{
this.port = port;
this.host = host;
}
public void connect() throws UnknownHostException, IOException, Exception
{
connection = new Socket(new String(host), port);
System.out.println("Client is ready.");
bfr = new BufferedReader(new InputStreamReader(connection.getInputStream()));
}
public void readInput() throws IOException
{
String input;
if(input = bfr.readLine()) != null)
{
System.out.println(input);
}
}
public static void main(String[] args) throws UnknownHostException, IOException, Exception
{
SocketClient socketClient = new SocketClient("localhost", 19999);
try {
socketClient.connect();
try
{
while(true)
{
socketClient.readInput();
}
}
}
}
}
Server:
public class MultipleSocketServer implements Runnable {
private Socket connection;
private String TimeStamp;
private int ID;
static PrintWriter writer;
private static File file;
public static void main(String[] args)
throws FileNotFoundException, UnsupportedEncodingException
{
int port = 19999;
int count = 0;
file = new File("E:/test.txt");
writer = new PrintWriter(file, "UTF-8");
try
{
ServerSocket socket = new ServerSocket(port);
System.out.println("MultipleSocketServer Initialized");
while (true)
{
Socket connection = socket.accept();
Runnable runnable = new MultipleSocketServer(connection, ++count);
Thread thread = new Thread(runnable);
thread.start();
}
}
}
MultipleSocketServer(Socket s, int i) {
this.connection = s;
this.ID = i;
}
public void run() {
try {
System.out.println("Connected: " + connection.getLocalSocketAddress() + " at port " + connection.getPort());
writer.println(ID + ": " + connection.getLocalSocketAddress() + " at port " + connection.getPort());
writer.flush();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(connection.getOutputStream()));
writer.write("MultipleSocketServer repsonded at " + new java.util.Date().toString());
writer.write("\n");
writer.flush();
}
finally {
try {
connection.close();
}
}
}
}
Analysis
It seems the server side closes connection after sending the data.
The client side has the following infinite loop:
while (true)
{
socketClient.readInput();
}
The loop can cause the CPU consumption: the method bfr.readLine() method call will return null immediately after the connection is closed.
Solution
Please consider changing the loop of the client side to read until "the end-of-connection":
String input;
while ((input = bfr.readLine()) != null) {
System.out.println(input);
}
Related
I'm basically trying to code a socket communication between multiple clients and a server.
I am getting this error java.net.SocketException: Connection reset. I have read some posts regarding this error, but none of the proposed solutions seems to solve my problem.
Here is the code for the Client : Client.java
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.Scanner;
import javafx.scene.web.PromptData;
public class Client {
private Socket socket;
private boolean running;
public Client(Socket socket) {
this.socket = socket;
running = true;
}
public void sendToServer(String message) throws IOException {
DataOutputStream outputStream = new DataOutputStream(socket.getOutputStream());
outputStream.writeUTF(message);
System.out.println("Die Nachricht : \"" + message + "\" wurde zu dem Server geschickt.");
// outputStream.close();
}
public String waitForNewMessage() throws IOException {
DataInputStream inputStream = new DataInputStream(socket.getInputStream());
String message = inputStream.readUTF();
// inputStream.close();
return message;
}
public void stop() throws IOException {
socket.close();
running = false;
}
public boolean isRunning() {
if (running == true) {
return true;
}
return false;
}
public String promptForNewMessage() {
Scanner scanner = new Scanner(System.in);
System.out.println("Geben Sie eine Nachricht ein.");
String message = scanner.nextLine();
scanner.close();
return message;
}
public void processReceivedMessage(String message) {
System.out.println("Hier ist die Antwort des Servers : " + message);
}
public static void main(String[] args) throws IOException {
//Socket clientSocket = new Socket(args[0], Integer.parseInt(args[1]));
Socket clientSocket = new Socket("localhost",9999);
Client client = new Client(clientSocket);
while (true) {
String message = client.promptForNewMessage();
client.sendToServer(message);
String response = client.waitForNewMessage();
client.processReceivedMessage(response);
if(response.contains("\\exit")) {
System.out.println("Die Verbindung wird geschlossen");
client.stop();
break;
}
}
}
}
The code for the server : Server.java
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class Server {
private int port;
private boolean running;
private ServerSocket serverSocket;
private static Server instance;
private Server() throws IOException {
this.port = loadPortFromConfig("config-datei.txt");
this.running = true;
this.serverSocket = new ServerSocket(this.port);
}
public int loadPortFromConfig(String path) throws FileNotFoundException {
File config = new File(path);
Scanner in = new Scanner(config);
if (in.hasNextLine()) {
String line = in.nextLine().split(":")[1];
in.close();
return Integer.parseInt(line);
}
in.close();
return 9999;
}
public static Server getInstance() throws IOException {
if (instance == null) {
instance = new Server();
}
return instance;
}
public static void main(String[] args) throws IOException {
Server server = Server.getInstance();
if (args.length != 0) {
server.port = Integer.parseInt(args[0]);
}
System.out.println("Der Port des Servers ist : " + server.port);
while(true) {
Socket socket = null;
try {
socket = server.serverSocket.accept();
System.out.println("A new client is connected : " + socket);
System.out.println("Assigning a new thread for this client");
Thread t = new Connection(socket);
t.start();
}
catch(IOException e) {
e.printStackTrace();
}
}
}
static class Connection extends Thread {
private Socket clientSocket;
private boolean running;
public Connection(Socket clientSocket) {
this.clientSocket = clientSocket;
this.running = true;
}
#Override
public void run() {
String fromClient = "";
while(true) {
try {
fromClient = waitForMessage();
System.out.println("Der Client hat die Nachricht : \"" + fromClient + "\" geschickt");
if(fromClient.contains("\\exit")) {
System.out.println("Client "+this.clientSocket + "sneds exit...");
System.out.println("Closing connection.");
sendToClient(fromClient);
System.out.println("Connection closed");
running = false;
break;
}
sendToClient(fromClient);
}
catch(IOException e) {
e.printStackTrace();
}
}
}
public String waitForMessage() throws IOException {
DataInputStream inputStream = new DataInputStream(clientSocket.getInputStream());
String message = inputStream.readUTF();
// inputStream.close();
return message;
}
public void sendToClient(String message) throws IOException {
DataOutputStream outputStream = new DataOutputStream(clientSocket.getOutputStream());
outputStream.writeUTF("Die folgende Nachricht : \"" + message + "\" wurde geschickt");
// outputStream.close();
}
}
}
The error occurs in the line fromClient = waitForMessage(); in the try catch block of the server code
This code calls the method waitForMessage() in the line : String message = inputStream.readUTF();
Do you have any recommendations ? thank you
java.net.SocketException: Connection reset
This means the OS has reseted the connection because the process on the other end is no longer running. It looks like your client crashes after processing first reply from the server.
Scanner scanner = new Scanner(System.in);
scanner.close();
Do not close Scanners operating on System.in. This will close System.in and you will not be able to read anything anymore from there.
Basically I'm writing a 2 way communication client server program. The client sends requests to the server and server responds accordingly. The requests have to do with adding or removing tokens from a list of tokens stored on the server. The client side seems to work fine, the requests are being sent to the server. However it seems that the server is not receiving any request from the client and I have no idea why. I've attached the code:
client
package;
import java.io.*;
import java.net.Socket;
import java.util.Scanner;
public class TokenClient {
private static final int PORT_NUMBER = 9999;
private Socket socket;
private InputStream inStream;
private OutputStream outStream;
private Scanner inStreamScanner;
private PrintWriter outStreamPrinter;
public static void main(String[] args) {
new TokenClient().go();
}
void go() {
try {
System.out.println(
"Enter commands of the form \"CONNECT IP-address\", \"SUBMIT token\", \"REMOVE token\" or \"QUIT\"\n");
Scanner consoleScanner = new Scanner(System.in);
// java.io.BufferedReader consoleInputReader = new
// BufferedReader(new InputStreamReader(System.in));
String command = "";
while (!command.equals("QUIT") && consoleScanner.hasNextLine()) {
command = consoleScanner.nextLine(); // consoleInputReader.readLine();
processCommand(command);
}
System.out.println("Goodbye!");
consoleScanner.close();
} catch (IOException e) {
System.out.println("An exception occurred: " + e);
e.printStackTrace();
}
}
void processCommand(String userCommand) throws IOException {
if (userCommand.startsWith("SUBMIT"))
sendMessageToServer(userCommand);
else if (userCommand.startsWith("REMOVE"))
sendMessageToServer(userCommand);
else if (userCommand.equals("QUIT"))
closeConnectionToServer();
else if (userCommand.startsWith("CONNECT")) {
closeConnectionToServer();
connectToServer(userCommand);
} else
System.out.println("Invalid user command: " + userCommand);
}
void closeConnectionToServer() {
if (socket != null && !socket.isClosed()) {
try {
System.out.println("Disconnecting from server...");
sendMessageToServer("QUIT");
socket.close();
System.out.println("Connection to server closed.");
} catch (IOException e) {
System.out.println("An exception occurred: " + e);
e.printStackTrace();
}
}
}
void connectToServer(String connectCommand) throws IOException {
String ipAddress = connectCommand.substring(8).trim();
System.out.println("Connecting to server at " + ipAddress + ", port " + PORT_NUMBER + "...");
socket = new Socket(ipAddress, PORT_NUMBER);
inStream = socket.getInputStream();
outStream = socket.getOutputStream();
inStreamScanner = new Scanner(inStream);
outStreamPrinter = new PrintWriter(outStream);
System.out.println("Connected to server.");
}
void sendMessageToServer(String command) {
System.out.println("Sending message to server: " + command + "...");
if (socket == null || socket.isClosed())
System.out.println("Not possible - not connected to a server");
else {
outStreamPrinter.println(command); // send the message to the server
// NB: client doesn't check if tokens are valid
outStreamPrinter.flush(); // do so immediately
// Receive response from server:
if (!command.equals("QUIT") && inStreamScanner.hasNextLine()) {
String response = inStreamScanner.nextLine();
System.out.println("Response from server: " + response);
}
}
}
}
server
package;
import java.net.*;
import java.util.ArrayList;
import java.util.Scanner;
import java.io.*;
public class server {
private static Socket s;
private static Scanner inStreamScanner;
private static int PORT_NUMBER = 9999;
private static InputStream inStream;
private static OutputStream outStream;
private static PrintWriter outStreamPrinter;
private static ArrayList<String> ts = new ArrayList<String>();
public static void main(String[] args) throws IOException{
ServerSocket ss = new ServerSocket(PORT_NUMBER);
server serverInstance = new server();
server.s = ss.accept();
System.out.println("Client connected");
inStream = s.getInputStream();
outStream = s.getOutputStream();
inStreamScanner = new Scanner(inStream);
outStreamPrinter = new PrintWriter(outStream);
serverInstance.run();
}
public void run() {
try {
try {
doService();
} finally {
s.close();
}
} catch (IOException e) {
System.err.println(e);
}
}
public void doService() throws IOException{
while(true) {
if(inStreamScanner.hasNext())
return;
else {
outStreamPrinter.println("NO REQUEST");
outStreamPrinter.flush();
String request = inStreamScanner.next();
outStreamPrinter.println("Request received: " +request);
outStreamPrinter.flush();
handleServerRequest(request);
}
}
}
public void handleServerRequest(String request) throws IOException{
if(request.startsWith("SUBMIT")) {
String token = extractNum(request);
addtoTS(token);
} else if(request.startsWith("REMOVE")) {
String token = extractNum(request);
removefromTS(token);
} else if(request.startsWith("QUIT")) {
s.close();
} else {
outStreamPrinter.println("UNKNOWN REQUEST");
outStreamPrinter.flush();
}
}
public String extractNum(String request) {
String str = request;
String numberOnly = str.replaceAll("[^0-9]", " ");
return numberOnly;
}
public void addtoTS(String token) {
if(ts.contains(token)) {
outStreamPrinter.println("OK");
outStreamPrinter.flush();
}else {
ts.add(token);
outStreamPrinter.println("OK");
outStreamPrinter.flush();
}
}
public void removefromTS(String token) {
if(ts.contains(token)) {
ts.remove(token);
outStreamPrinter.println("OK");
outStreamPrinter.flush();
}else {
outStreamPrinter.println("ERROR: TOKEN NOT FOUND");
outStreamPrinter.flush();
}
}
}
I haven't run the code, but there seems to be an issue in your doService() method on the server side. You have an infinite loop, but the entire method returns (and thus the program also quits) as soon as the input stream recieves a new line character (when the client sends a request). So, it seems your program would quit when it receives the first command from the client. I'd also recommend closing more gently (ie check in the loop for end rather than closing the socket directly).
So, I'd define a private class variable boolean listening; or something like that. Then in the main() method, set it to true after the socket has been initialized (when the client has connected).
Change your doService() to something similar to the following:
public void doService() throws IOException
{
while(listening)
{
if(inputStreamReader.hasNext())
{
String request = inStreamScanner.next();
outStreamPrinter.println("Request received: " +request);
outStreamPrinter.flush();
handleServerRequest(request);
}
}
}
And change how you handle the QUIT command:
from
else if(request.startsWith("QUIT"))
{
s.close();
}
to
else if(request.startsWith("QUIT"))
{
listening = false;
}
The socket will be closed by the finally in run().
I have a problem with the communication between a server and a client. I am trying to figure out a way of the communicating automatically because they have to exchange some parameters. However, with the code I wrote the server either keeps on sending the same message to the client after the client confirms the message or the client receives nothing at all. The sockets and everything have been setup up before. The function sendString() and receiveString() are identical inboth code examples. Is there a proper way of doing this? I dont get why this doesnt work...
Server:
String buffer;
while(true){
buffer = client.receiveString();
if(buffer != null && buffer.equals("ready")){
System.out.println("Client is ready");
client.sendString("ready");
while(true){
buffer = client.receiveString();
if(buffer != null && buffer.equals("k")){
System.out.println("stopped");
break;
}
}
break;
}
}
public String receiveString() throws IOException{ //From the client class
if(dataIn.available() > 0){
int length = dataIn.readInt();
byte[] b = new byte[length];
dataIn.readFully(b, 0, b.length);
return new String(b, Charset.forName("UTF-8"));
}
return null;
}
public void sendString(String msg) throws IOException{
byte[] b = msg.getBytes(Charset.forName("UTF-8"));
dataOut.writeInt(b.length);
dataOut.write(b);
}
Client:
String buffer;
while(true){
sendString("ready");
buffer = receiveString();
if(buffer!=null)
System.out.println(buffer);
if(buffer != null && buffer.equals("ready")){
System.out.println("Server is ready");
sendString("k");
break;
}
}
This code might work in your case:
Client.java
public class Client {
public static void main(String[] args) throws Exception {
try (Socket socket = new Socket("localhost", 8080)) {
try (BufferedOutputStream out = new BufferedOutputStream(socket.getOutputStream());
Scanner in = new Scanner(socket.getInputStream())) {
System.out.println("Client: sending ready.");
writeLine("ready", out);
System.out.println("Client: sent ready.");
String line = in.nextLine();
if ("ready".equals(line)) {
System.out.println("Client: server is ready");
writeLine("k", out);
}
}
}
}
private static void writeLine(final String line, final BufferedOutputStream out) throws IOException {
out.write((line +"\n").getBytes());
out.flush();
}
}
Server.java:
public class Server {
public static void main(String[] args) throws Exception {
boolean running = true;
try (ServerSocket socket = new ServerSocket(8080, 0)) {
while (running) {
System.out.println("Waiting for client accept.");
try (final Socket client = socket.accept();
final Scanner in = new Scanner(client.getInputStream());
final BufferedOutputStream out = new BufferedOutputStream(client.getOutputStream())) {
System.out.println("Waiting for client ready.");
String line = readLine(in);
if ("ready".equals(line)) {
writeLine("ready", out);
while (running) {
line = readLine(in);
if (line != null && line.equals("k")) {
System.out.println("Server: received stop signal");
running = false;
} else {
Thread.sleep(100);
System.out.println("Server: waiting for command.");
}
}
}
}
}
}
}
private static String readLine(final Scanner in) {
String line = in.nextLine();
System.out.println("Server: client sent " + line);
return line;
}
private static void writeLine(final String line, final BufferedOutputStream out) throws IOException {
out.write((line + "\n").getBytes());
out.flush();
}
}
So what is happening here?
Server socket waits for a client. If client connects, it waits for it to send something (in a blocking manner!). If its "ready", it checks for other commands.
Note: This only works for a single server<->client connection at a time. Dunno if this suites your application. The Server gets shutdown if client sends "k", like in your case.
I have this class where i try to create a number of threads and then i need to send a message to the server over all the threads or using a specific thread. I can't seem to find a way to do that in this way I can only send using the last thread that was created.
Here is the class:
public class test{
public test(){
}
public static void main(String[] args){
MultiThreadChatClient mc = new MultiThreadChatClient();
test st = new test();
for(int i =0; i<=4; i++){
mc.createThreads();
}
while (true) {
System.out.print("type your message: ");
Scanner s = new Scanner(System.in);
String ss = s.nextLine();
ss = ss.trim().replaceAll(" +", " ");
mc.sendMessage(ss);
try
{
Thread.sleep(400);
}
catch(InterruptedException e)
{
// this part is executed when an exception (in this example InterruptedException) occurs
System.out.println("Exeption: " + e);
}
}
}
}
Here's the Client thread class:
public class MultiThreadChatClient implements Runnable {
// The client socket
private static Socket clientSocket = null;
// The output stream
private static PrintStream os = null;
// The input stream
private static BufferedReader br;
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";
if (args.length < 2) {
System.out.println("Usage: java MultiThreadChatClient <host> <portNumber>\n"
+ "Now using host=" + host + ", portNumber=" + portNumber);
} else {
host = args[0];
portNumber = Integer.valueOf(args[1]).intValue();
}
}
/*
* Open a socket on a given host and port. Open input and output streams.
*/
public void createThreads(){
try {
clientSocket = new Socket("localhost", 2222);
inputLine = new BufferedReader(new InputStreamReader(System.in));
os = new PrintStream(clientSocket.getOutputStream());
br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
} catch (UnknownHostException e) {
System.err.println("Don't know about host " + 2222);
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to the host " + 2222);
}
//}
/*
* 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 && br != null) {
new Thread(new MultiThreadChatClient()).start();
}
}
public void sendMessage(String mes){
os.println(mes);
}
/*
* 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 = br.readLine()) != null){
System.out.println(responseLine);
if (responseLine.indexOf("*** Bye") != -1)
break;
}
closed = true;
} catch (IOException e) {
System.err.println("IOException1234: " + e);
}
}
}
Here's the server code:
public class MultiThreadChatServerSync {
// 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 maxClientsCount = 50;
private static final clientThread[] threads = new clientThread[maxClientsCount];
public static void main(String args[]) {
// The default port number.
int portNumber = 2222;
if (args.length < 1) {
System.out.println("Usage: java MultiThreadChatServerSync <portNumber>\n"
+ "Now using port number=" + portNumber);
} else {
portNumber = Integer.valueOf(args[0]).intValue();
}
/*
* 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);
//System.out.println(serverSocket.getPort());
} 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 < maxClientsCount; i++) {
if (threads[i] == null) {
(threads[i] = new clientThread(clientSocket, threads)).start();
//System.out.println("A new client is created");
break;
}
}
if (i == maxClientsCount) {
PrintStream os = new PrintStream(clientSocket.getOutputStream());
os.println("Server too busy. Try later.");
os.close();
clientSocket.close();
}
} catch (IOException e) {
System.out.println(e);
}
}
}
}
class clientThread extends Thread {
MultiThreadChatServerSync ms = new MultiThreadChatServerSync();
private String clientName = null;
//private DataInputStream is = null;
private BufferedReader br = null;
private PrintStream os = null;
private Socket clientSocket = null;
private final clientThread[] threads;
private int maxClientsCount;
public clientThread(Socket clientSocket, clientThread[] threads) {
this.clientSocket = clientSocket;
this.threads = threads;
maxClientsCount = threads.length;
//System.out.println("Inside the Client thread");
}
public void run() {
MultiThreadChatServerSync mss = new MultiThreadChatServerSync();
int maxClientsCount = this.maxClientsCount;
clientThread[] threads = this.threads;
//System.out.println("Inside the run");
try {
/*
* Create input and output streams for this client.
*/
br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
os = new PrintStream(clientSocket.getOutputStream());
while (true) {
String line = br.readLine();
System.out.println("message received via Client port: " + clientSocket.getPort());
System.out.println("Received: " + line);
}
} catch (IOException e) {
}
}
}
So, is there a way to create 5 threads and then send the message over all of them or choose one specific thread out of them?
To be able to have a client which starts several sessions, and to be able to send data to one or several of them, the client must change in a few ways.
The static references in the client must be removed.
The Socket instances must be created and stored in the main thread (the writers will be used to send messages on behalf of one or more client sessions)
Each client session is now only responsible for reading (the reader is passed via the constructor).
The code is based on your original code, and meant to be a template for further enhancements: It will manage 5 client sessions, and be able to write to 1 or many.
The new main Thread (As an example, the Scanner will first ask the message for client #1, then 2, 3, 4 and next will broadcast to all, in a loop):
public class MultiThreadChatClientRunner {
final int NO_CLIENTS = 5;
//final String HOST_IP = "192.168.2.7";
final String HOST_IP = "localhost";
public static void main(String[] args) {
new MultiThreadChatClientRunner().start();
}
private void start() {
Socket[] sockets = new Socket[NO_CLIENTS];
PrintStream[] writers = new PrintStream[NO_CLIENTS];
BufferedReader[] readers = new BufferedReader[NO_CLIENTS];
for (int i = 0; i < NO_CLIENTS; i++) {
System.out.println("Creating client number "+i);
Socket clientSocket;
try {
clientSocket = new Socket(HOST_IP, 2222);
writers[i] = new PrintStream(clientSocket.getOutputStream());
readers[i] = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
new Thread(new MultiThreadChatClient(i, readers[i])).start();
} catch (IOException e) {
e.printStackTrace();
}
}
int clientId = 0;
Scanner s = new Scanner(System.in);
while (true) {
System.out.print("type your message for client #"+clientId);
String ss = s.nextLine();
ss = ss.trim().replaceAll(" +", " ");
writers[clientId].println(ss);
clientId = (clientId+1)%NO_CLIENTS;
// Test to broadcast to all clients
if (clientId == 4) {
for (int i = 0; i<NO_CLIENTS; i++)
writers[i].println("Broadcast message: "+ss);
}
try {
Thread.sleep(400);
} catch (InterruptedException e) {
System.out.println("Thread was interrupted");
break;
}
}
s.close();
}
}
The new client, which is much simpler than before:
public class MultiThreadChatClient implements Runnable {
// The client socket
private Socket clientSocket = null;
// The output stream
private PrintStream os = null;
// The input stream
private final BufferedReader br;
private final int clientId;
public MultiThreadChatClient(int clientId, BufferedReader br) {
super();
this.clientId = clientId;
this.br = br;
}
/*
* 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 = br.readLine()) != null) {
System.out.printf("Client #%d received message=%s\n", clientId, responseLine);
if (responseLine.indexOf("*** Bye") != -1)
break;
}
} catch (IOException e) {
System.err.println("IOException1234: " + e);
}
}
}
And the server, which is nearly identical, but manages closes better, and has some more logging to show which client is communicating.
public class MultiThreadChatServerSync {
// 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 maxClientsCount = 50;
private static final ClientThread[] threads = new ClientThread[maxClientsCount];
public static void main(String args[]) {
// The default port number.
int portNumber = 2222;
if (args.length < 1) {
System.out.println(
"Usage: java MultiThreadChatServerSync <portNumber>\n" + "Now using port number=" + portNumber);
} else {
portNumber = Integer.valueOf(args[0]).intValue();
}
/*
* 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);
// System.out.println(serverSocket.getPort());
} 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 {
System.out.println("Awaiting a new connection on "+serverSocket.getLocalPort());
clientSocket = serverSocket.accept();
int i = 0;
for (i = 0; i < maxClientsCount; i++) {
if (threads[i] == null) {
(threads[i] = new ClientThread(i, clientSocket)).start();
// System.out.println("A new client is created");
break;
}
}
if (i == maxClientsCount) {
PrintStream os = new PrintStream(clientSocket.getOutputStream());
os.println("Server too busy. Try later.");
os.close();
clientSocket.close();
}
} catch (IOException e) {
System.out.println(e);
}
}
}
}
class ClientThread extends Thread {
private BufferedReader br = null;
private PrintStream os = null;
private final Socket clientSocket;
private final int clientId;
public ClientThread(int clientId, Socket clientSocket) {
this.clientSocket = clientSocket;
this.clientId = clientId;
}
public void run() {
try {
/*
* Create input and output streams for this client.
*/
br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
os = new PrintStream(clientSocket.getOutputStream());
String line = "";
while ((line = br.readLine()) != null) {
System.out.printf("Client <%d> received message=<%s> via Client port: <%d>\n", clientId, line, clientSocket.getPort());
// Echo it back (as a test)
os.println(line);
}
br.close();
os.close();
clientSocket.close();
} catch (IOException e) {
}
System.out.println("Client has closed the session");
}
}
Let me know if you have any further questions at this time.
Trying to build a simple multi-threaded chat server that runs via command prompt. The clients do connect to the server and the server will hold multiple clients, however when trying to send messages from one client to the other, or even notifying a client of another user logging in, nothing comes up on the client command prompt.
public class Server {
private static ServerSocket servSock;
private static Socket clientSock;
private static ArrayList<ClientThread> clientList;
private static int IDcount = 0;
public static void main(String args[]){
// Get command line arguments.
if (args.length != 3) {
System.out.println("Required arguments: server port, block duration, timeout");
return;
}
int port = Integer.parseInt(args[0]);
int blockDur = Integer.parseInt(args[1]);
int timeout = Integer.parseInt(args[2]);
try{
servSock = new ServerSocket(port);
clientList = new ArrayList<ClientThread>();
}
catch(IOException ex){
System.err.println(ex);
}
while (true) {
try {
clientSock = servSock.accept();
ClientThread thread = new ClientThread(clientSock);
clientList.add(thread);
thread.start();
} catch (IOException e) {
System.out.println(e);
}
}
}
private synchronized static void broadcast(String msg){
System.out.print(msg);
for(int i = 0; i < clientList.size(); i++){
ClientThread client = clientList.get(i);
client.send(msg);
}
}
synchronized static void unlist(int id){
for(int i = 0; i < clientList.size(); i++){
ClientThread thread = clientList.get(i);
if(thread.id == id){
clientList.remove(i);
return;
}
}
}
static class ClientThread extends Thread {
Socket sock;
BufferedReader tIn;
PrintWriter tOut;
int id;
String username;
String msg;
ClientThread(Socket sock){
id = IDcount++;
this.sock = sock;
try{
tIn = new BufferedReader(new InputStreamReader(sock.getInputStream()));
tOut = new PrintWriter(sock.getOutputStream());
username = tIn.readLine();
broadcast(username + " logged in");
}
catch(IOException ex){
System.err.println(ex);
}
}
public void run(){
boolean loggedIn = true;
while(loggedIn){
try{
msg = tIn.readLine();
}
catch (IOException ex){
System.err.println(ex);
}
String[] parts = msg.split("\\s",2);
String type = parts[0];
Client code is similar
public class Client{
private static Socket clientSock;
private static BufferedReader in;
private static PrintWriter out;
private static Scanner scan;
public static void main(String[] args) throws IOException {
if (args.length != 2) {
System.out.println("Required arguments: server IP, server port");
return;
}
String host = args[0];
int port = Integer.parseInt(args[1]);
clientSock = new Socket(host, port);
in = new BufferedReader(new InputStreamReader(clientSock.getInputStream()));
out = new PrintWriter(clientSock.getOutputStream());
scan = new Scanner(System.in);
new ListenFromServer().start();
boolean online = true;
System.out.println("Enter your username:");
String username = scan.nextLine();
out.println(username);
while(online){
System.out.println("> ");
String msg = scan.nextLine();
String[] parts = msg.split("\\s");
String type = parts[0];
send(msg);
if(type.equalsIgnoreCase("logout")){
online = false;
}
}
logoff();
}
static void send(String msg) throws IOException{
out.println(msg);
}
private static void logoff() throws IOException{
in.close();
out.close();
scan.close();
clientSock.close();
}
static class ListenFromServer extends Thread{
public void run(){
while(true){
try{
String msg = in.readLine();
System.out.println(msg);
}
catch(IOException ex){
System.err.println(ex);
}
}
}
}
}
When you send data with PrintWriter.println(), data write to buffer. You must call PrintWriter.flush() after println to send data to or from the server immediately.
And when you call username = tIn.readLine(); in ClientThread constructor, you block main-thread, because constructor calls in main-thread. So, while connected user won't send username, other clients can't connect.