I'm newbie on the network programming. I want to make an simple server/client program in order to understand the basics of sockets. But unfortunately I can't understand one concept. Can I call readUTF() method before before client sends message? Because when I call second time this method my program crashes.
Error:
java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(Unknown Source)
at java.net.SocketInputStream.read(Unknown Source)
at java.net.SocketInputStream.read(Unknown Source)
at java.io.DataInputStream.readUnsignedShort(Unknown Source)
at java.io.DataInputStream.readUTF(Unknown Source)
at java.io.DataInputStream.readUTF(Unknown Source)
at Messaging.ServerSideConnection.receiveData(ServerSideConnection.java:59)
at Messaging.Server.printInputs(Server.java:88)
at Messaging.Server$2.run(Server.java:35)
at java.lang.Thread.run(Unknown Source)
Server:
package Messaging;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class Server {
private static final String configId = "SERVER_CONFİG_ID_";
private static final int port = 6066;
private volatile ArrayList<ServerSideConnection> connections;
public static void main(String[] args){
new Server();
}
public Server(){
connections = new ArrayList<>();
Thread acceptConnections = new Thread(new Runnable(){
public void run() {
try {
acceptConnections(port);
} catch (IOException e) {
e.printStackTrace();
}
}
});
Thread printInputs = new Thread(new Runnable(){
public void run() {
while(true){
printInputs();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
acceptConnections.start();
printInputs.start();
try {
acceptConnections.join();
printInputs.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void acceptConnections(int port) throws IOException{
ServerSocket serverSocket = new ServerSocket(port);
while(true){
System.out.println("SERVER : Listening..");
ServerSideConnection connection = new ServerSideConnection(serverSocket.accept());
connection.sendData(configId + Integer.toString(connection.getId()));
connections.add(connection);
System.out.println("SERVER : Connected to " + connection.getSocket().getInetAddress());
}
}
public void controlConnectionLife(){
int instantSize = connections.size();
for(int i=0;i<instantSize;i++){
if(!connections.get(i).isConnected()){
connections.get(i).killConnection();
connections.remove(i);
i--;
}
}
}
public void printInputs(){
for (ServerSideConnection connection : connections){
System.out.println(connection.isConnected());
try {
System.out.println(connection.receiveData());
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
public class ServerSideConnection {
private static int count;
private int id;
private Socket socket;
private DataInputStream input;
private DataOutputStream output;
public ServerSideConnection(Socket socket){
this.socket = socket;
initOutputStream();
initInputStream();
count++;
id = count;
}
private void initInputStream(){
try {
InputStream in = socket.getInputStream();
input = new DataInputStream(in);
} catch (IOException e) {
e.printStackTrace();
}
}
private void initOutputStream(){
try {
output = new DataOutputStream(socket.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
public void killConnection(){
try {
output.close();
input.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public String receiveData() throws IOException{
return input.readUTF();
}
public void sendData(String msg) throws IOException{
output.writeUTF(msg);
output.flush();
}
public boolean isConnected(){
return socket.isConnected();
}
public int getId(){
return id;
}
public Socket getSocket(){
return socket;
}
public DataInputStream getInput() {
return input;
}
public DataOutputStream getOutput() {
return output;
}
}
Client:
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ConnectException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
public class ClientSideConnection {
private static final String configId = "SERVER_CONFİG_ID_";
private static final int port = 6066;
private static final String host = "localhost";
private int id;
private Socket socket;
private DataInputStream input;
private DataOutputStream output;
public static void main(String[] args){
try {
new ClientSideConnection(port,host);
} catch (IOException e) {
e.printStackTrace();
}
}
public ClientSideConnection(int port, String host) throws UnknownHostException, IOException{
boolean connected = false;
while(!connected){
try{
socket = new Socket(host,port);
connected = true;
System.out.println("CLIENT : Connected to " + socket.getInetAddress());
}
catch(ConnectException e){
connected = false;
}
}
initOutputStream();
initInputStream();
String receivedId = receiveData();
if(receivedId.substring(0, 17).equals(configId))
id = Integer.parseInt(receivedId.substring(17,receivedId.length()));
sendTestData();
}
private void initInputStream(){
try {
input = new DataInputStream(socket.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
private void initOutputStream(){
try {
output = new DataOutputStream(socket.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
public void killConnection(){
try {
output.close();
input.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public String receiveData() throws IOException{
return input.readUTF();
}
public void sendData(String msg) throws IOException{
output.writeUTF(msg);
output.flush();
}
public int getId() {
return id;
}
public void sendTestData(){
Scanner scan = new Scanner(System.in);
System.out.print("enter test msg: ");
String msg = scan.nextLine();
try {
sendData(msg);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("msg sended!");
}
}
As the exception message states, the second call to readUTF is failing because the connection is being closed by the client. The code running the client currently follows the sequence of:
Establish connection
Setup input and output streams
Read data from server
Send data to server
After sending data to the server, there is no code left and no loop to repeat the process of sending/receiving, so the client closes its end of the connection and exits. You'll need to add a 5th step to your sequence:
Establish connection
Setup input and output streams
Read data from server
Send data to server
Jump to 3 until a stopping condition is met
One approach to this sequence could be:
public class Client {
public static void main(String[] args) {
Client client = new Client();
boolean sucessful;
do {
String data = client.receiveData();
successful = client.sendData(data);
} while(successful);
client.close();
}
public Client() {
//setup connection and in/output streams
}
public String receiveData() {
//read from input
}
public boolean sendData(String data) {
//send data
}
public void close() {
}
}
Related
i am trying to create a simple chat app using java sockets, the server is threaded, when a client connects its socket is added to an ArrayList, so that i can send to all in that list.
the problem is when 3 clients are connected, the for loop that sends doesn't work properly, for ex : client 0 sends to both 1 and 2 but client 2 doesn't send to anyone :(
The server and the ClientHandler :
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
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;
public class MainServer {
private static int portnumber = 6968;
static ArrayList <ClientHandler> allClients = new ArrayList<>();
public static void main(String[] args) throws Exception {
// init
// server works by default on localhost
ServerSocket serversocket = new ServerSocket(portnumber);
int clientNo = 0;
System.out.println("server is running on port : " + portnumber);
while (true) {
// creating a socket for each connection
Socket clientsocket = null;
try {
// receiving incoming requests from users/clients
clientsocket = serversocket.accept();
// input and output from client
PrintWriter out = new PrintWriter(clientsocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(clientsocket.getInputStream()));
// create a threads
ClientHandler ch = new ClientHandler(clientsocket, "Client#" + clientNo, in, out);
// adding to the clientList
allClients.add(ch);
System.out.println(ch.clientName + " has joined");
Thread clientThread = new Thread(ch);
clientThread.start();
// decrease when user leaves
clientNo++;
} catch (Exception e) {
clientsocket.close();
e.printStackTrace();
System.exit(1);
//out.close();
//in.close();
//clientSocket.close();
//serverSocket.close();
}
}
}
}
// handle client requests
public class ClientHandler implements Runnable{
public String clientName;
public Socket clientsocket = null;
public boolean active = false;
private BufferedReader inp;
private PrintWriter out;
private final String EXIT_STR = "exit";
public Scanner clientSc = new Scanner(System.in);
public ClientHandler(Socket socket, String name, BufferedReader inp, PrintWriter out) {
this.clientsocket = socket;
this.clientName = name;
this.inp = inp;
this.out = out;
// active when the thread is created
this.active = true;
}
#Override
public void run() {
// getting the output temp
String recivedMsg = "";
while (true) {
try {
recivedMsg = inp.readLine();
System.out.println(recivedMsg);
// check for ctrl+C
if (recivedMsg.equals(this.EXIT_STR)){
// send to all
System.out.println(this.clientName + " exits");
// close the connection and break
this.active = false;
this.clientsocket.close();
// bye
break;
}
// send to all except me
for (ClientHandler client : MainServer.allClients){
if (!client.clientName.equals(this.clientName)){
client.out.println(this.clientName + ":" + recivedMsg);
client.out.flush();
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
try {
// clean
this.clientsocket.close();
this.inp.close();
this.out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
The client :
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
public class Client {
private String hostName;
private int portNumber;
// set connction and server
public PrintWriter out = null;
public BufferedReader in = null;
public Socket clientSocket = null;
Client(String hostName, int port) {
this.hostName = hostName;
this.portNumber = port;
// setting the connction
this.setConnection();
}
private void setConnection () {
try {
this.clientSocket = new Socket(this.hostName, this.portNumber);
this.out = new PrintWriter(this.clientSocket.getOutputStream(), true);
this.in = new BufferedReader(new InputStreamReader(this.clientSocket.getInputStream()));
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
}
public void sendMessageToServer(String msg) {
//System.out.println("The msg is : " + msg);
out.println(msg);
}
public String readMessage() {
String outputMsg = "";
try {
outputMsg = in.readLine();
} catch (IOException e) {
e.printStackTrace();
}
return outputMsg;
}
// shit cleaning
public void closeSession(){
try {
this.out.close();
this.in.close();
this.clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
System.out.println("Session has been terminated!");
}
public static void main(String args[]) throws IOException{
// init
String host = "localhost";
int port = 6968;
Client newClient = new Client(host, port);
// // send a message
Scanner sc = new Scanner(System.in);
Thread sendMsg = new Thread(new Runnable() {
#Override
public void run() {
while (true) {
try {
String userInput = sc.nextLine();
newClient.sendMessageToServer(userInput);
if (userInput.equals("exit")) {
System.exit(1);
}
} catch (Exception e) {
System.exit(1);
}
}
}
});
Thread getMsg = new Thread(new Runnable() {
#Override
public void run() {
while (true) {
String msgRead = "";
try {
msgRead = newClient.readMessage();
System.out.println(msgRead);
} catch (Exception e) {
System.exit(1);
}
}
}
});
sendMsg.start();
getMsg.start();
}
}
I think the problem is here :
// send to all except me
for (ClientHandler client : MainServer.allClients){
if (!client.clientName.equals(this.clientName)){
client.out.println(this.clientName + ":" + recivedMsg);
client.out.flush();
break;
}
}
The fix is straightforward: remove the break statement from the loop where you think the problem is.
This break statement causes the loop through all the ClientHandlers to stop as soon as it sends the message to one client. You don't want this: you want this loop to keep going and send the message to all clients other than the one that wrote the message.
I have a java server with multiple clients connections. If one client sends a message to the server v the server broadcasts the message to all clients. What should I change in the code so that it answers only the client who sent the message?
Hereby the code:
EchoServer.java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class EchoServer
{
public static void main(String[] args) throws IOException
{
EchoServer server = new EchoServer();
server.start();
}
private ArrayList<PrintWriter> writers = new ArrayList<>();
public void start() {
ServerSocket serverSocket = null;
try
{
serverSocket = new ServerSocket(5000);
while (true) {
Socket clientSocket = serverSocket.accept();
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
writers.add(out);
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
Thread t = new ClientHandler(in, this);
t.start();
}
}
catch (IOException e)
{
System.out.println("Exception caught when trying to listen on port 5000 or listening for a connection");
System.out.println(e.getMessage());
}
finally
{
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public synchronized void broadcast(String inputLine) {
for (PrintWriter writer : writers) {
writer.println(inputLine);
}
}
}
EchoClient.java
import java.io.*;
import java.net.*;
public class EchoClient
{
public static void main(String[] args) throws IOException
{
String hostName = "localhost";
int portNumber = 5000;
Socket echoSocket = null;
try
{
echoSocket = new Socket(hostName, portNumber);
PrintWriter out = new PrintWriter(echoSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
Thread t = new ServerHandler(in);
t.start();
String userInput;
while ((userInput = stdIn.readLine()) != null)
{
out.println(userInput);
}
}
catch (UnknownHostException e)
{
System.err.println("Don't know about host " + hostName);
System.exit(1);
}
catch (IOException e)
{
System.err.println("Couldn't get I/O for the connection to " + hostName);
System.exit(1);
}
finally
{
echoSocket.close();
}
}
}
ServerHandler
import java.io.BufferedReader;
import java.io.IOException;
public class ServerHandler extends Thread {
private BufferedReader reader;
public ServerHandler(BufferedReader reader) {
super();
this.reader = reader;
}
#Override
public void run() {
String readLine;
try {
while((readLine = reader.readLine()) != null) {
System.out.println(readLine);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
ClientHandler
import java.io.BufferedReader;
import java.io.IOException;
public class ClientHandler extends Thread {
private BufferedReader reader;
private EchoServer server;
public ClientHandler(BufferedReader reader, EchoServer server)
{
this.reader = reader;
this.server = server;
}
#Override
public void run() {
while (true) {
String inputLine;
try {
while ((inputLine = reader.readLine()) != null)
{
server.broadcast(inputLine);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Currently, when you receive a message from a client, your ClientHandler calls the server's broadcast method. Here is how I would only echo to one client.
1) Pass the clientSocket into the ClientHandler. So the code below would replace the code in the EchoServer.
Thread t = new ClientHandler(in, clientSocket, this);
t.start();
Then your client handler would have a socket, that it could write back too.
import java.io.BufferedReader;
import java.io.IOException;
import java.net.Socket;
public class ClientHandler extends Thread {
private BufferedReader reader;
private Socket clientSocket;
private EchoServer server;
public ClientHandler(BufferedReader reader, Socket clientSocket EchoServer server)
{
this.reader = reader;
this.server = server;
this.clientSocket = clientSocket;
}
#Override
public void run() {
while (true) {
String inputLine;
try {
while ((inputLine = reader.readLine()) != null)
{
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
out.println(inputLine);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
I'm trying to do a simple group chat where there's a server and several clients.
The objective is when a client sends a message to the server, the server just sends that message back to all the other clients. I had the server send a message writen by him send to all the clients but he didn't send the clients message.
Server code:
package Group;
import java.net.*;
import java.io.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.*;
public class GroupServer extends Thread {
private ServerSocket server;
protected List<ClientHandler> clients;
public static void main(String[] args) throws IOException {
new GroupServer(9876);
}
public GroupServer(int port) {
try {
this.server = new ServerSocket(port);
System.out.println("New server initialized!");
clients = Collections.synchronizedList(new ArrayList<ClientHandler>());
this.start();
} catch (Exception e) {
e.printStackTrace();
}
}
public void run() {
while (true) {
try {
Socket client = server.accept();
System.out.println(client.getInetAddress().getHostName() + " connected");
ClientHandler newClient = new ClientHandler(client);
clients.add(newClient);
new SendMessage(clients);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
class ClientHandler {
protected Socket client;
protected PrintWriter out;
protected DataInputStream in;
public ClientHandler(Socket client) {
this.client = client;
try {
this.out = new PrintWriter(client.getOutputStream());
this.in = new DataInputStream(client.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
}
class SendMessage extends Thread {
protected List<ClientHandler> clients;
protected String userInput;
protected String sendMessage;
protected BufferedReader stdIn;
protected DataInputStream in;
public SendMessage(List<ClientHandler> clients) {
this.clients = clients;
this.userInput = null;
this.start();
}
public void run() {
System.out.println("New Communication Thread Started");
if (clients.size() == 1) {
System.out.println("Enter message:");
}
try {
if (clients.size() > 0) {
this.stdIn = new BufferedReader(new InputStreamReader(System.in));
while ((this.userInput = stdIn.readLine()) != null) {
if (userInput != null & userInput.length() > 0) {
for (ClientHandler client : clients) {
sendMessage = client.in.readUTF();
client.out.println(sendMessage);
client.out.flush();
Thread.currentThread();
Thread.sleep(1 * 1000);
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
The client code:
package Group;
import java.net.*;
import java.io.*;
import java.util.logging.*;
public class GroupClient {
protected Socket client;
protected BufferedReader in;
public static void main(String[] args) {
new GroupClient("Localhost", 9876);
}
public GroupClient(String hostName, int ip) {
try {
this.client = new Socket(hostName, ip);
this.in = new BufferedReader(new InputStreamReader(
this.client.getInputStream()));
String buffer = null;
while ((buffer = in.readLine()) != null) {
System.out.println(buffer);
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
I think the error is in the Server, more preciselly on the SendMessage class.
Thank you for the attention.
You have just one thread "SendMessage" for all the clients.
The very first time you call client.in.readUTF() in a loop, the thread blocks till that client has sent something. Since all the other clients are handled by the same thread. All of them are blocked too.
Either you have one thread per client socket or go the nio selector way (preferrable).
Also fix the issues mentioned by #jingx.
For synchronized arraylist, use CopyOnWriteArrayList. It is specifically meant for these kind of usecases. Synchronization help in concurrent addition and deletion but not during concurrent iteration. CopyOnWriteArrayList solves that problem.
I want to write a simple server that listens on a port and spawns new threads for handling new connections.
I attempted to use try-with-resources for accepting new connections but failed because sockets in child threads seem to be closed immediately and I don't understand why.
Here are 2 simplified examples.
a) The working example of the server (without try-with-resources):
package MyTest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class MyServerA implements Runnable {
private int port;
private ServerSocket serverSocket;
public MyServerA(Integer port) {
this.port = port;
}
#Override
public void run() {
try {
serverSocket = new ServerSocket(port);
} catch(IOException ioe) {
System.err.println("error opening socket. " + ioe.getStackTrace());
}
while (true) {
Socket clientSocket = null;
try {
clientSocket = serverSocket.accept();
ClientServiceThread cliThread = new ClientServiceThread(clientSocket);
cliThread.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
class ClientServiceThread extends Thread {
private Socket s;
boolean goOn = true;
ClientServiceThread(Socket s) {
this.s = s;
}
public void run() {
BufferedReader in = null;
PrintWriter out = null;
try {
in = new BufferedReader(new InputStreamReader(this.s.getInputStream()));
out = new PrintWriter(new OutputStreamWriter(this.s.getOutputStream()));
while (goOn) {
final String req = in.readLine();
if (req != null) {
System.out.println("got: " + req);
out.println("you said: " + req);
out.flush();
if (req.contains("bye")) {
System.out.println("closing thread");
goOn = false;
}
}
}
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
MyServerA a = new MyServerA(30000);
a.run();
}
}
b) Exactly the same, but with try-with-resources (doesn't work):
package MyTest;
import java.io.BufferedReader;
public class MyServerB implements Runnable {
private int port;
private ServerSocket serverSocket;
public MyServerB(Integer port) {
this.port = port;
}
#Override
public void run() {
try {
serverSocket = new ServerSocket(port);
} catch(IOException ioe) {
System.err.println("error opening socket. " + ioe.getStackTrace());
}
while (true) {
try (Socket clientSocket = serverSocket.accept();) {
ClientServiceThread cliThread = new ClientServiceThread(clientSocket);
cliThread.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
class ClientServiceThread extends Thread {
private Socket s;
boolean goOn = true;
ClientServiceThread(Socket s) {
this.s = s;
}
public void run() {
BufferedReader in = null;
PrintWriter out = null;
try {
in = new BufferedReader(new InputStreamReader(this.s.getInputStream()));
out = new PrintWriter(new OutputStreamWriter(this.s.getOutputStream()));
while (goOn) {
final String req = in.readLine();
if (req != null) {
System.out.println("got: " + req);
out.println("you said: " + req);
out.flush();
if (req.contains("bye")) {
System.out.println("closing thread");
goOn = false;
}
}
}
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
MyServerB b = new MyServerB(30000);
b.run();
}
}
The example in a) works like expected.
The example in b) accepts a connection but closes it immediately.
Can someone explain to me why and tell me how I do this properly?
The structure
try (resource = ...) {
}
is equivalent to
resource = null;
try {
resource = ...;
} finally {
if (resource != null) {
resource.close();
}
}
That's it. It is just a syntactic sugar, just shorter way to write the same. So, when you put statement Socket clientSocket = serverSocket.accept(); into try-with-resource block you actually close it once you leave the block.
This structure is good when processing of stream is done synchronously, i.e. when you open stream, read or write and close it.
In your case you get the stream and process it in separate thread and therefore cannot close it immediately. Client should decide to close the stream itself. For example when user press button "disconnect" or when server sends special application level command "close connection" or if IOException is thrown.
I am working on multi chat in java. I'm kinda new to this socket thing.
There is a problem with my code but I can't find it. I think the problem is in clientSocket.getInputStream(); . I inserted System.out.println before and after this statement. I can't see the second one. It seems that client can connect to port but cannot get inputs from server. If you can help me, I really would be thankful. It has been 3 hours but still I can't find the problem
ClientSide.java
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class ClientSide
{
public Socket clientSocket;
public ObjectOutputStream outStream;
public ObjectInputStream inStream;
public String receiveMessage=null,sendMessage=null;
public GuiScreen gui;
public void run()
{
try
{
clientSocket = new Socket("localhost", 2222);
inStream = new ObjectInputStream(clientSocket.getInputStream());
outStream = new ObjectOutputStream(clientSocket.getOutputStream());
outStream.flush();
while(true)
{
try
{
receiveMessage = (String)inStream.readObject();
gui.appendMessage(receiveMessage);
}
catch(ClassNotFoundException classNot)
{System.err.println("data received in unknown format");}
}
}
catch(UnknownHostException unknownHost)
{System.err.println("You are trying to connect to an unknown host!");}
catch(IOException ioException)
{ioException.printStackTrace();}
}
public String readMessage()
{
String text = "";
try
{
text = (String)inStream.readObject();
}
catch (ClassNotFoundException | IOException e)
{e.printStackTrace();}
return text;
}
public void sendMessage(String msg)
{
try
{
outStream.writeObject(msg);
outStream.flush();
}
catch(IOException ioException){ioException.printStackTrace();}
}
public ClientSide()
{}
private void showGui()
{
gui = new GuiScreen(this,"Client Side");
}
public static void main(String[] args)
{
ClientSide client = new ClientSide();
client.showGui();
client.run();
}
}
MultiCheatServer.java
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class MultiChatServer
{
public static ClientThread[] clientThreads = new ClientThread[10];
public static int portNumber = 2222;
public static ServerSocket serverSocket = null;
public static Socket clientSocket = null;
public static void openPort()
{
try
{
serverSocket = new ServerSocket(portNumber);
}
catch (IOException e)
{e.printStackTrace();}
}
public static void connectToClients()
{
while(true)
{
try
{
clientSocket = serverSocket.accept();
}
catch (IOException e)
{e.printStackTrace();}
for(int i = 0; i<=9; ++i)
{
if(clientThreads[i] == null)
{
clientThreads[i] = new ClientThread(clientSocket,clientThreads);
clientThreads[i].start();
break;
}
}
}
}
public static void main(String[] args)
{
openPort();
connectToClients();
}
}
ClientThread.java
import java.io.DataInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PrintStream;
import java.net.Socket;
public class ClientThread extends Thread
{
public ObjectInputStream inStream = null;
public ObjectOutputStream outStream = null;
public Socket clientSocket;
public ClientThread[] clientThreads;
public ClientThread (Socket cSocket,ClientThread[] cThreads)
{
clientSocket = cSocket;
clientThreads = cThreads;
}
public void sendMessage(String msg)
{
try
{
outStream.writeObject(msg);
outStream.flush();
}
catch (IOException e)
{e.printStackTrace();}
}
public String readMessage()
{
String text = null;
try
{
text = (String)inStream.readObject();
}
catch (ClassNotFoundException | IOException e)
{e.printStackTrace();}
return text;
}
public void run()
{
String text;
String name;
try
{
inStream = new ObjectInputStream(clientSocket.getInputStream());
outStream= new ObjectOutputStream(clientSocket.getOutputStream());
outStream.flush();
sendMessage("Name:\n");
name = readMessage().trim();
sendMessage("type /quit if you want to quit\n");
for(int i = 0 ; i <=9 ; ++i)
if(clientThreads[i]!=null && clientThreads[i]!=this)
clientThreads[i].sendMessage(name + "has come\n");
while(true)
{
text = readMessage() ;
if(text.startsWith("/quit"))
break;
for(int i = 0; i<=9; ++i)
if(clientThreads[i] != null)
clientThreads[i].sendMessage("<" + name + ">" + text);
}
for(int i = 0 ;i<=9; ++i)
if(clientThreads[i]!=null && clientThreads[i]!=this)
clientThreads[i].sendMessage(name + " has disconnected\n");
sendMessage("Bye\n");
inStream.close();
outStream.close();
for(int i = 0;i<=9;++i)
if(clientThreads[i]==this)
clientThreads[i] = null;
}
catch (IOException e)
{e.printStackTrace();}
}
}
One problem I see is that you have to decide who creates the input stream first, the server or the client.
ObjectInputStream tries to read a serialization header in its constructor, and if the output stream has not written it yet it will wait. Now both client and server are waiting for the other to "speak" first.