I am going for the simplest explanation. My Java TCP project has a server and three clients.
The server has a ClientThread.
The clients each has a ServerThread and a UserThread.
The workflow is:
1. The UserThread of a client (say, client_0) gets user input and then sends a message to the server.
2. The ClientThread of the server captures the message from client_0 and sends another message to the ServerThread of a different client (say, client_1).
3. The ServerThread of client_1 then sends back another message to the ClientThread running in the server;
The message of step 3 is not reaching the server.
There are total 3 clients, say client_0, client_1 and client_2.
The original idea is that if client_0 requests the server then the server communicates with client_1 and client_2. That's why the line if(i==cid) continue; in the for loop in the server. But, if i comment out this line, the server communicates with the client_0 (which is unnecessary semantically) and the messaging problem doesn't happen. After that the server communicates with client_1 and the problem appears again.
The server can receive message from the ServerThread of the client (client_0) that sent the original request (msgToServer.println("get list");) from it's UserThread to initiate the whole process. But Server cannot get message from any other client's ServerThread even though it can send message to others and all the client programs are identical and all the ServerThreads and UserThreads should work the same eway. How is it even possible?
Server:
package serverftp;
import java.io.*;
import java.net.*;
public class ServerFTP {
static String[] id = {"cp 1","cp 2","cp 3"};
static String[] pass = {"123","456","789"};
static BufferedReader[] msgFromClient = new BufferedReader[3];
static PrintWriter[] msgToClient = new PrintWriter[3];
static InputStream[] fileFromClient = new InputStream[3];
static OutputStream[] fileToClient = new OutputStream[3];
public static void main(String[] args) throws Exception {
ServerSocket welcome = new ServerSocket(6789);
// connecting the three clients
for(int i=0; i<3; i++) {
System.out.println("Waiting for Client "+i);
Socket clientSocket;
clientSocket = welcome.accept();
while(true) {
System.out.println("Connecting Client "+i);
BufferedReader fromClient = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
PrintWriter toClient = new PrintWriter(clientSocket.getOutputStream(),true);
// get id pass from client
String clientId = fromClient.readLine();
System.out.println(clientId);
String clientPass = fromClient.readLine();
System.out.println(clientPass);
// check id pass and feedback
if(clientId.equals(id[i]) && clientPass.equals(pass[i])) {
toClient.println("ok");
msgFromClient[i] = fromClient;
msgToClient[i] = toClient;
fileFromClient[i] = clientSocket.getInputStream();
fileToClient[i] = clientSocket.getOutputStream();
break;
} else {
toClient.println("error");
}
}
ClientThread ct = new ClientThread(i);
ct.start();
System.out.println("Client "+i+" connected!");
}
welcome.close();
}
}
class ClientThread extends Thread {
int cid;
String msg;
public ClientThread(int client_id) {
cid = client_id;
try {
// telling client it's serial
ServerFTP.msgToClient[cid].println(Integer.toString(cid));
} catch(Exception ex) {
ex.printStackTrace();
}
}
#Override
public void run() {
while(true) {
try {
// get request from receiver
msg = ServerFTP.msgFromClient[cid].readLine();
if(msg.equals("get list")) {
System.out.println(cid+" "+msg);
msg = ServerFTP.msgFromClient[cid].readLine();
System.out.println(cid+" "+msg);
for(int i=0; i<3; i++) {
if(i==cid) continue;
// send sender request for file list
ServerFTP.msgToClient[i].println("give list");
System.out.println("request sent to client "+i);
// get file count from sender
msg = ServerFTP.msgFromClient[i].readLine();
System.out.println("file count caught!!!"); // THIS LINE NEVER EXECUTES
System.out.println("File count "+msg);
}
}
} catch(Exception ex) {
ex.printStackTrace();
}
}
}
}
The line System.out.println("file count caught!!!"); is never called.
Client:
package clientftp_1;
import java.io.*;
import java.net.*;
public class ClientFTP_1 {
static String[] allPaths = { "...path...\\client_1_folder",
"...path...\\client_2_folder",
"...path...\\client_3_folder"};
public static void main(String[] args) throws Exception {
InetAddress inetAddress = InetAddress.getLocalHost();
Socket server = new Socket(inetAddress,6789);
int myId;
// login phase
BufferedReader fromUser = new BufferedReader(new InputStreamReader(System.in));
BufferedReader fromServer = new BufferedReader(new InputStreamReader(server.getInputStream()));
PrintWriter toServer = new PrintWriter(server.getOutputStream(),true);
InputStream getFile = server.getInputStream();
OutputStream sendFile = server.getOutputStream();
while(true) {
System.out.println("id: ");
String msg = fromUser.readLine();
toServer.println(msg);
System.out.println("password: ");
msg = fromUser.readLine();
toServer.println(msg);
msg = fromServer.readLine();
if(msg.equals("ok")) {
System.out.println("Connection Successful!");
myId = Integer.parseInt(fromServer.readLine());
System.out.println("Client serial is: "+myId);
System.out.println("Folder path is: "+allPaths[myId]);
break;
} else {
System.out.println("Error! Try again please.");
}
}
ServerThread st = new ServerThread(allPaths[myId],fromUser,fromServer,toServer,getFile,sendFile);
st.start();
UserThread ut = new UserThread(allPaths[myId],fromUser,fromServer,toServer,getFile,sendFile);
ut.start();
}
}
class ServerThread extends Thread {
String folderPath;
String msg;
BufferedReader msgFromServer,msgFromUser;
PrintWriter msgToServer;
InputStream fileFromServer;
OutputStream fileToServer;
public ServerThread(String path,BufferedReader fromUser,BufferedReader fromServer,PrintWriter toServer,InputStream getFile,OutputStream sendFile) throws Exception {
folderPath = path;
msgFromUser = fromUser;
msgFromServer = fromServer;
msgToServer = toServer;
fileFromServer = getFile;
fileToServer = sendFile;
}
#Override
public void run() {
System.out.println("Server Thread Started");
while(true) {
try {
// receive request
msg = msgFromServer.readLine();
System.out.println("request received from server");
if(msg.equals("give list")) {
// get filenames
File folder = new File(folderPath);
File[] fileList = folder.listFiles();
int cnt = fileList.length;
System.out.println("count calculated");
// sned file count to server
msgToServer.println(Integer.toString(cnt));
System.out.println("count sent to server"); // THIS LINE PRINTS
}
} catch(Exception ex) {
ex.printStackTrace();
}
}
}
}
class UserThread extends Thread {
String folderPath;
String msg;
BufferedReader msgFromServer,msgFromUser;
PrintWriter msgToServer;
InputStream fileFromServer;
OutputStream fileToServer;
public UserThread(String path,BufferedReader fromUser,BufferedReader fromServer,PrintWriter toServer,InputStream getFile,OutputStream sendFile) throws Exception {
folderPath = path;
msgFromUser = fromUser;
msgFromServer = fromServer;
msgToServer = toServer;
fileFromServer = getFile;
fileToServer = sendFile;
}
#Override
public void run() {
System.out.println("USer Thread Started");
while(true) {
try {
// input from user
msg = msgFromUser.readLine();
if(msg.equals("get list")) {
// send request to server
msgToServer.println("get list");
msgToServer.println("fahim list");
}
} catch(Exception ex) {
ex.printStackTrace();
}
}
}
}
The line System.out.println("count sent to server"); is printed. That means the message sending line before that has executed with no problem.
I know the login system in the server is stupid. But it is 'ok' for this work. Everything explained above happens after all the clients have connected and logged in to the server.
I think I have found the problem. I was using the same socket for a client program's ServerThread and UserThread. So while the ServerThread is trying to response to the server, most probably the message is going to another different thread in the server that is listening for message (thinking the message comes from UserThread) through the same socket.
Related
I want to edit this code, so it could accept more client join on my server. This server is just used to accept one client's connection, and it can send, and receive messages. But I want to make it a "Multiplayer" Server. Many clients connected to one server. Here's the Server side code, and the Client side code:
I would really appreciate your help!
My Server Code:
import java.net.*;
import java.lang.*;
public class RecordAppServer {
public static void main(String[] args) throws IOException {
final int port = 8136;
System.out.println("Server waiting for connection on port "+port);
ServerSocket ss = new ServerSocket(port);
Socket clientSocket = ss.accept();
System.out.println("Recieved connection from "+clientSocket.getInetAddress()+" on port "+clientSocket.getPort());
//create two threads to send and recieve from client
RecieveFromClientThread recieve = new RecieveFromClientThread(clientSocket);
Thread thread = new Thread(recieve);
thread.start();
SendToClientThread send = new SendToClientThread(clientSocket);
Thread thread2 = new Thread(send);
thread2.start();
}}
class RecieveFromClientThread implements Runnable
{
Socket clientSocket=null;
BufferedReader brBufferedReader = null;
public RecieveFromClientThread(Socket clientSocket)
{
this.clientSocket = clientSocket;
}//end constructor
public void run() {
try{
brBufferedReader = new BufferedReader(new InputStreamReader(this.clientSocket.getInputStream()));
String messageString;
while(true){
while((messageString = brBufferedReader.readLine())!= null){//assign message from client to messageString
if(messageString.equals("EXIT"))
{
break;//break to close socket if EXIT
}
System.out.println("From Client: " + messageString);//print the message from client
//System.out.println("Please enter something to send back to client..");
}
this.clientSocket.close();
System.exit(0);
}
}
catch(Exception ex){System.out.println(ex.getMessage());}
}
}//end class RecieveFromClientThread
class SendToClientThread implements Runnable
{
PrintWriter pwPrintWriter;
Socket clientSock = null;
public SendToClientThread(Socket clientSock)
{
this.clientSock = clientSock;
}
public void run() {
try{
pwPrintWriter =new PrintWriter(new OutputStreamWriter(this.clientSock.getOutputStream()));//get outputstream
while(true)
{
String msgToClientString = null;
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));//get userinput
msgToClientString = input.readLine();//get message to send to client
pwPrintWriter.println(msgToClientString);//send message to client with PrintWriter
pwPrintWriter.flush();//flush the PrintWriter
//System.out.println("Please enter something to send back to client..");
}//end while
}
catch(Exception ex){System.out.println(ex.getMessage());}
}//end run
}//end class SendToClientThread
My Client Code:
import java.io.*;
import java.net.*;
public class RecordAppClient {
public static void main(String[] args)
{
try {
Socket sock = new Socket("192.168.0.2",8136);
SendThread sendThread = new SendThread(sock);
Thread thread = new Thread(sendThread);thread.start();
RecieveThread recieveThread = new RecieveThread(sock);
Thread thread2 =new Thread(recieveThread);thread2.start();
} catch (Exception e) {System.out.println(e.getMessage());}
}
}
class RecieveThread implements Runnable
{
Socket sock=null;
BufferedReader recieve=null;
public RecieveThread(Socket sock) {
this.sock = sock;
}//end constructor
public void run() {
try{
recieve = new BufferedReader(new InputStreamReader(this.sock.getInputStream()));//get inputstream
String msgRecieved = null;
while((msgRecieved = recieve.readLine())!= null)
{
System.out.println("From Server: " + msgRecieved);
//System.out.println("Please enter something to send to server..");
}
}catch(Exception e){System.out.println(e.getMessage());}
}//end run
}//end class recievethread
class SendThread implements Runnable
{
Socket sock=null;
PrintWriter print=null;
BufferedReader brinput=null;
public SendThread(Socket sock)
{
this.sock = sock;
}//end constructor
public void run(){
try{
if(sock.isConnected())
{
System.out.println("Client connected to "+sock.getInetAddress() + " on port "+sock.getPort());
this.print = new PrintWriter(sock.getOutputStream(), true);
while(true){
//System.out.println("Type your message to send to server..type 'EXIT' to exit");
brinput = new BufferedReader(new InputStreamReader(System.in));
String msgtoServerString=null;
msgtoServerString = brinput.readLine();
this.print.println(msgtoServerString);
this.print.flush();
if(msgtoServerString.equals("EXIT"))
break;
}//end while
sock.close();}}catch(Exception e){System.out.println(e.getMessage());}
}//end run method
}//end class
You'll need to implement a multithreaded server.
The general structure will be the following:
while(true) {
1) Wait for client requests (Socket client = server.accept();)
2) Create a thread with the client socket as parameter
a) The new thread creates I/O streams (just like youre doing
with the PrintWriter and BufferedReader objects)
b) Communicate with client (in your example -
brBufferedReader.readLine())
3) Remove thread once the service is provided.
}
I suggest you take a look at the Oracle documentation:
https://www.oracle.com/technetwork/java/socket-140484.html#multi
This might also be useful:
http://tutorials.jenkov.com/java-multithreaded-servers/multithreaded-server.html
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.
So I've been making a chatroom based off a single server, where clients can connect and talk in the chatroom. At the moment each client can speak to the server and the server returns what the client has said. But I've been struggling to broadcast a single client message to all clients.
I stored all socket connections in an ArrayList and then created a for loop to iterate through all the connections to echo a single message to all the connected clients. Unfortunately my code is not working and I can't understand why. Here's my code:
Handler code:
public class Handler implements Runnable {
private Socket client;
String message = "";
public Handler(Socket client){
this.client = client;
}
#Override
public void run() {
try{
try{
ChatClient CCG = new ChatClient();
Scanner INPUT = new Scanner(client.getInputStream()); //input data from the server
PrintWriter OUT = new PrintWriter(client.getOutputStream()); //output data from the server
while(true){
if(!INPUT.hasNextLine()){ //if nothings there, end it
return;
}
message = INPUT.nextLine(); //get input
System.out.println("Client HANDLER said: "+ message);
//echo out what the client says to all the users
for(int i=1; i<= ChatServer.ConnectionArray.size(); i++){
Socket TEMP_SOCK = (Socket) ChatServer.ConnectionArray.get(i-1);
PrintWriter TEMP_OUT = new PrintWriter(TEMP_SOCK.getOutputStream());
TEMP_OUT.println(message);
TEMP_OUT.flush();
System.out.println("Sent to: " + TEMP_SOCK.getLocalAddress().getHostName()); //displyed in the console
}
}
}finally{
client.close();
}
}catch(Exception X){
X.printStackTrace();
}
}
}
EDIT: Changed client.getOutputStream() to TEMP_SOCK.getOutputStream() but still no luck :/
Server code:
public class ChatServer {
public static ServerSocket server;
public static boolean ServerOn=true;
public static ArrayList<Socket> ConnectionArray = new ArrayList<Socket>(); //holds all the connections so messages can be echoed to all the other users
public static ArrayList<String> CurrentUsers = new ArrayList<String>(); //current users
public static void main(String[] args){
//ExecutorService executor = Executors.newFixedThreadPool(30); //number of clients allowed to join the server
try {
server = new ServerSocket(14001);
System.out.println("Server started!");
System.out.println("Waiting for clients to connect...");
while(true){
try {
//ChatClient chatClient = new ChatClient();
Socket client = server.accept();
ConnectionArray.add(client); //add socket to connection array and allows multiple users to enter server
System.out.println(ConnectionArray);
//CurrentUsers.add(chatClient.user);
//System.out.println("Current users: "+CurrentUsers);
System.out.println("Client connected from: " + client.getLocalAddress().getHostName()); //gets their ip address and local host name
Thread thread = new Thread(new Handler(client));
thread.start();
} catch (IOException e) {
e.printStackTrace();
}
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
Client Code:
public class ChatClient extends javax.swing.JFrame {
Socket sock;
String message;
int port = 14001;
PrintWriter write;
BufferedReader read;
String user;
ArrayList<String> usersOnline = new ArrayList();
InputStreamReader streamreader;
boolean userConnected = false;
public ChatClient() {
initComponents();
}
/*public class Incoming implements Runnable{
public void run(){
try{
sock = new Socket("localhost",14001);
write = new PrintWriter(out);
} catch (IOException ex) {
ex.printStackTrace();
}
}
}*/
public void addUser(){
onlineUsersTextArea.append(user+" \n");
usersOnline.add(user);
System.out.println(usersOnline);
}
/*public void Send(){
String bye = (user + ": :Disconnect");
try{
write.println(bye);
write.flush();
}catch(Exception ex){
chatTextArea.append("Could not send disconnect message. \n");
}
}*/
public void userDisconnected(){
chatTextArea.append(user + " has disconnected.\n");
}
public void Disconnect(){
try{
chatTextArea.append("Disconnected.\n"); // Notify user that they have disconnected
write.flush();
sock.close(); // Closes the socket
System.out.println(user + " has disconnected.");
}catch(Exception e){
chatTextArea.append("Failure to disconnect.\n");
}
userConnected = false;
onlineUsersTextArea.setText(""); // Remove name from online users
usernameInputField.setEditable(true); // Allows a username to be created
}
private void connectButtonActionPerformed(java.awt.event.ActionEvent evt) {
if(userConnected == false){
user = usernameInputField.getText();
usernameInputField.setEditable(false);
try{
sock = new Socket("localhost", port);
InputStreamReader sReader = new InputStreamReader(sock.getInputStream());
write = new PrintWriter(sock.getOutputStream());
read = new BufferedReader(sReader);
addUser();
chatTextArea.append(user + " has connected. \n");
write.println(user+" has connected."); // Display username of client when connection is established
write.flush(); // Flushes the stream
userConnected = true;
} catch (IOException ex) {
chatTextArea.append("Failed to connect.\n");
usernameInputField.setEditable(true);
ex.printStackTrace();
}
}else if(userConnected == true){
chatTextArea.append("You are already connected. \n");
}
}
private void disconnectButtonActionPerformed(java.awt.event.ActionEvent evt) {
Disconnect();
userDisconnected();
}
private void sendButtonActionPerformed(java.awt.event.ActionEvent evt) {
String nothing = "";
if((userInputTextArea.getText()).equals(nothing)){
userInputTextArea.setText("");
userInputTextArea.requestFocus();
}else{
try{
chatTextArea.append(user + ": " + userInputTextArea.getText()+" \n");
write.println(user + ": " + userInputTextArea.getText());
write.flush();
}catch(Exception ex){
chatTextArea.append("Message failed to send. \n");
}
userInputTextArea.setText("");
userInputTextArea.requestFocus();
}
userInputTextArea.setText("");
userInputTextArea.requestFocus();
}
private void usernameInputFieldActionPerformed(java.awt.event.ActionEvent evt) {
}
/**
* #param args the command line arguments
*/
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new ChatClient().setVisible(true);
}
});
}
}
My for loop is in the Handler class. I'm not understanding why the message isn't being sent out to the clients. The TEMP_SOCK (temporary socket) should work (I think) but the server only receives the messages but doesn't echo them.
Any help on how to go about this would be really appreciated! Thank you :)
PrintWriter TEMP_OUT = new PrintWriter(client.getOutputStream()); means you're always sending to the same client, you should use PrintWriter TEMP_OUT = new PrintWriter(TEMP_SOCK.getOutputStream());
I am trying to create a text messaging program with three files (main function file, client file, server file)
If "-l" is present on the command line, it will run as a server, otherwise it will run as a client
Command line arguments to run server:
java DirectMessengerCombined -l 3000
Command line arguments to run client:
java DirectMessengerCombined 3000
Text of error:
java.net.BindException: Address already in use
at java.net.PlainSocketImpl.socketBind(Native Method)
at java.net.AbstractPlainSocketImpl.bind(AbstractPlainSocketImpl.java:387)
at java.net.ServerSocket.bind(ServerSocket.java:375)
at java.net.ServerSocket.<init>(ServerSocket.java:237)
at java.net.ServerSocket.<init>(ServerSocket.java:128)
at DirectMessengerServer.run(DirectMessengerServer.java:41)
at DirectMessengerServer.runSend(DirectMessengerServer.java:111)
at DirectMessengerServer.run(DirectMessengerServer.java:58)
at DirectMessengerServer.<init>(DirectMessengerServer.java:16)
at DirectMessengerCombined.main(DirectMessengerCombined.java:21)
Screenshot of error (server on left, client on right):
The problem with the screenshot is that the left window (server) was able to send and recieve text messages to the client until the server sends the "hello" message.
Code of main Server file:
import java.io.*;
import java.net.*;
import java.util.*;
import javax.imageio.IIOException;
public class DirectMessengerServer
{
private String[] serverArgs; // <-- added variable
private static Socket socket;
public boolean keepRunning = true;
public DirectMessengerServer(String[] args) throws IOException
{
// set the instance variable
this.serverArgs = args;
run();
}
public String[] ServerRun(String[] args) throws IOException
{
//How do I get the String[] args in this method be able to access it in the run methods?
serverArgs = args;
serverArgs = Arrays.copyOf(args, args.length);
return serverArgs;
}
Thread ListeningLoop = new Thread();
//run method of ServerRecieve
public void run() throws IOException
{
try
{
int port_number1 = Integer.valueOf(serverArgs[1]);
ServerSocket serverSocket = new ServerSocket(port_number1);
socket = serverSocket.accept();
while(keepRunning)
{
//Reading the message from the client
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String MessageFromClient = br.readLine();
System.out.println("Message received from client: "+ MessageFromClient);
// ServerSend.start();
runSend();
}
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
finally
{
}
}
Thread ServerSend = new Thread ();
//Run method of ServerSend
public void runSend()
{
while(keepRunning)
{
System.out.println("Server sending thread is now running");
try
{
//Send the message to the server
OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
//creating message to send from standard input
String newmessage = "";
try
{
// input the message from standard input
BufferedReader input= new BufferedReader(
new InputStreamReader(System.in));
String line = "";
line= input.readLine();
newmessage += line + " ";
}
catch ( Exception e )
{
System.out.println( e.getMessage() );
}
String sendMessage = newmessage;
bw.write(sendMessage + "\n");
bw.flush();
System.out.println("Message sent to client: "+sendMessage);
run();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
finally
{
}
}
}
}
Code of Client file:
import java.io.*;
import java.net.*;
import java.util.*;
import static java.nio.charset.StandardCharsets.*;
public class DirectMessengerClient
{
private String[] clientArgs; // <-- added variable
private static Socket socket;
public boolean keepRunning = true;
public DirectMessengerClient(String[] args) throws IOException
{
// set the instance variable
this.clientArgs = args;
run(args);
}
public String[] ClientRun(String[] args)
{
clientArgs = args;
clientArgs = Arrays.copyOf(args, args.length);
return clientArgs;
}
Thread ClientSend = new Thread();
public void run(String args[]) throws IOException
{
System.out.println("Client send thread is now running");
while(keepRunning)
{
String port_number1= args[0];
System.out.println("Port number is: " + port_number1);
int port = Integer.valueOf(port_number1);
String host = "localhost";
InetAddress address = InetAddress.getByName(host);
socket = new Socket(address, port);
//Send the message to the server
OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
//creating message to send from standard input
String newmessage = "";
try
{
// input the message from standard input
BufferedReader input= new BufferedReader(new InputStreamReader(System.in));
String line = "";
line= input.readLine();
newmessage += line + " ";
}
catch ( Exception e )
{
System.out.println( e.getMessage() );
}
String sendMessage = newmessage;
bw.write(sendMessage + "\n");
bw.flush();
System.out.println("Message sent to server: "+sendMessage);
runClientRead(args);
}
}
Thread ClientRead = new Thread();
public void runClientRead(String args[]) throws IOException
{
System.out.println("Client recieve/read thread is now running");
//Integer port= Integer.valueOf(args[0]);
//String host = "localhost";
//InetAddress address = InetAddress.getByName(host);
//socket = new Socket(address, port);
//Get the return message from the server
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String MessageFromServer = br.readLine();
System.out.println("Message received from server: " + MessageFromServer);
}
}
Code of main function file:
import java.io.IOException;
public class DirectMessengerCombined
{
public static void main(String[] args) throws IOException
{
DirectMessengerClient client1 = null;
DirectMessengerServer server1 = null;
for (int i = 0; i < args.length; i++)
{
if (args.length == 1)
{
client1 = new DirectMessengerClient(args);
client1.ClientRun(args);
}
else if (args.length == 2)
{
server1 = new DirectMessengerServer(args);
server1.ServerRun(args);
}
i=args.length + 20;
}
}
}
My question is not only how to resolve the error (there's plenty of other questions that covered this) but why wasn't the error triggered the first time the messages were sent/received to/from the server?
I am creating a program where multiple clients can connect to a server. The message sent by a client will be broadcast to all other client connections on the server.
My problem is that the message is broadcast to only the client it has come from, and I cannot spot the error in my code.
Can anyone help me spot where the problem is or how I could improve the code?Thank you.
EDIT:
public class MsgClient{
private Socket client;
private ObjectInputStream input;
private DataOutputStream output;
private BufferedReader keyboard;
private String cmdInput;
public MsgClient(String name, String server, int port){
try{
client = new Socket(server, port);
DataInputStream sInput = new DataInputStream(client.getInputStream());
output = new DataOutputStream(client.getOutputStream());
input = new ObjectInputStream(client.getInputStream());
keyboard = new BufferedReader(new InputStreamReader(System.in));
output.writeUTF(name);
while(true){
System.out.println("Send a msg to the server: ");
cmdInput = keyboard.readLine();
output.writeUTF(cmdInput);
System.out.println(sInput.readUTF());
}
}
catch (Exception e){
e.printStackTrace();
}
}// end constructor
public static void main(String args[]) throws IOException {
if(args.length != 3)
throw new RuntimeException("Syntax: java MsgClient <username> <servername> <port>");
MsgClient aClient = new MsgClient(args[0], args[1], Integer.parseInt(args[2]));
} // end main
}
public class MsgServer {
public MsgServer(int PORT) throws IOException{
ServerSocket server = new ServerSocket(PORT);
System.out.println("Server Established...");
while(true){
Socket client = server.accept();
DataInputStream input = new DataInputStream(client.getInputStream());
ObjectOutputStream oo = new ObjectOutputStream(client.getOutputStream());
DataOutput output = new DataOutputStream(client.getOutputStream());
System.out.println("New client accepted");
String clientName = input.readUTF();
ClientHandler handler = new ClientHandler(clientName, client); // construct and run thread.
handler.start();
System.out.println("Handler started!");
}//end while
}//end of constructor
public static void main(String args[]) throws IOException {
if(args.length != 1)
throw new RuntimeException("Syntax: java MsgServer requires <PORT> number");
new MsgServer(Integer.parseInt(args[0]));
}
}
public class ClientHandler extends Thread {
Socket client;
DataInputStream din;
DataOutputStream dout;
String name;
String clientMsg;
protected static Vector socketVector = new Vector();
public ClientHandler (String name, Socket client) throws IOException{
this.name = name;
this.client = client;
din = new DataInputStream(client.getInputStream());
dout = new DataOutputStream(client.getOutputStream());
}
// Code run at every start()
public void run(){
try{
socketVector.addElement(this);
clientMsg = din.readUTF(); // inside or outside loop?
while(true){
broadcast( name + " has joined auction on IP " + client.getInetAddress());
broadcast( name + " says: " + clientMsg);
}
} catch(IOException ex){
System.out.println("-- Connection to user lost");
} finally{
socketVector.removeElement(this);
broadcast(name + " has left");
try{
client.close();
}catch (IOException ex){
System.out.println("socket to user already closed?");
}
}
}
Another issue is here, in the MsgClient code:
cmdInput = keyboard.readLine();
output.writeUTF(cmdInput);
System.out.println(sInput.readUTF());
A client will not receive a message until after it has sent one.
Where is the broadcast() method?
You are creating two sets of streams in the server. The accept loop shouldn't create any streams or do any I/O. All that should be done in the thread that handles the connection.
You don't need the ObjectInput/OutputStreams at all here.
When you get any IOException other than a read timeout on a socket you must close it. You should also print out the exception's own message, rather than just making up your own.