I am writing a basic chat server in java, however I have a couple of problems. When someone creates a client or server I would like them to be able to enter a command line argument which is used as a prefix for any message they send. This argument should be optional as well. I have got it working to an extent, for some reason when I send a message it sends the prefix twice, also it is not optional. Any help appreciated, Cheers!
public class ReadWriteThread extends Thread {
private BufferedReader input;
private PrintWriter output;
private String prefix;
public ReadWriteThread(InputStream input, OutputStream output, String prefix) {
this.input = new BufferedReader(new InputStreamReader(input));
this.output = new PrintWriter(output, true);
this.prefix = prefix;
}
public void run() {
try {
String line;
while ((line = input.readLine()) != null) {
output.println(prefix + " " + line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class Server {
public static void main(String[] args) {
try {
int port = Integer.parseInt(args[0]);
System.out.println("HELLO " + args[1]);
String prefix = args[1];
ServerSocket serverSocket = new ServerSocket(port);
System.err.println("Waiting for a client to connnect");
Socket socket = serverSocket.accept();
System.err.println("Accepted connection on port " + port);
new ReadWriteThread(System.in, socket.getOutputStream(), prefix).start();
new ReadWriteThread(socket.getInputStream(), System.out, prefix).start();
} catch (Exception e) {
e.printStackTrace();
System.err.println("\nUsage: java Server <port>");
}
}
}
public class Client {
public static void main(String[] args) {
Socket socket = null;
try {
int port = Integer.parseInt(args[0]);
String prefix = args[2];
socket = new Socket(args[1], port);
System.err.println("Connected to " + args[1] + " on port " + port);
new ReadWriteThread(System.in, socket.getOutputStream(), prefix).start();
new ReadWriteThread(socket.getInputStream(), System.out, prefix).start();
} catch (Exception e) {
e.printStackTrace();
System.err.println("\nUsage: java Client <port>");
}
}
}
Start a server by entering
java Server 7777 OPTIONALPREFIX
Start a client by entering
java Client 7777 localhost
Current output on server
Waiting for a client to connnect
Accepted connection on port 7777
-->-->hello
-->-->whats up
Both client and server prepend a prefix to their message and you've probably set --> as the prefix for both of them.
So the client might send
--> hello
then the server receives it and prepends his own prefix before logging it to the console
--> --> hello
Why is prefix not optional? Because you're always trying to read it, you never check the number of arguments passed to the program beforehand.
String prefix = args[1];
In order to access args[1] you first need to check whether args contains two arguments.
Related
This question already has answers here:
Server not reading client messages
(1 answer)
Reading data from a socket java
(1 answer)
Socket reading through buffered reader, not picking up on line
(2 answers)
Java - Socket not reading until client disconnects?
(4 answers)
Java ServerSocket won't send or receive messages from client
(1 answer)
Closed 3 years ago.
I have a client server program where the serverscoket will accept a connection form the client, and the client can receive messages from the server, but not vice versa.
The Client:
public class ChatClient {
private final String serverName;
private final int serverPort;
private Socket socket;
private OutputStream serverOut;
private InputStream serverIn;
private BufferedReader bufferedInputStream;
//private ArrayList<UserStatusListener> userListners = new ArrayList<UserStatusListener>();
private ChatClient(String serverName, int serverPort) {
super();
this.serverName = serverName;
this.serverPort = serverPort;
}
public static void main(String[] args) throws IOException {
ChatClient client = new ChatClient("localhost", 8818);
// Make sure serverboot is running and listenig first
if (! client.connect()) {
System.out.println("Connection Failed. Is ServerBoot running/listening?");
}else {
System.out.println("Connection succesful");
client.login("guest");
}
}
private boolean connect() {
// TODO Auto-generated method stub
try {
this.socket = new Socket(serverName, serverPort);
// get streams
this.serverOut = socket.getOutputStream();
this.serverIn = socket.getInputStream();
this.bufferedInputStream = new BufferedReader(new InputStreamReader(serverIn));
return true;
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
return false;
}
}
private void login (String login) throws IOException {
// send login to server
try {
String serverResponse = bufferedInputStream.readLine();
System.out.println("Server response: " + serverResponse);
while (bufferedInputStream.readLine() != null) {
System.out.println(bufferedInputStream.readLine());
}
String send = "Login : " + login;
serverOut.write(send.getBytes());
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
Snippets form the server:
try {
ServerSocket serverSocket = new ServerSocket(serverPortNumber);
while (true) {
// Listen for incoming connections and craete connection with accept
System.out.println("Waiting for client connection.... on localhost port " + serverPortNumber
+ ". \n Client connect via netcat localhost 8818");
Socket clientSocket = serverSocket.accept();// returns a client Socket object
System.out.println("Conenction established with " + clientSocket);
// Each new connection will be handled on a new thread and can run concurrenlty
ManageMultipleConnections multipleConnections = new ManageMultipleConnections(this, clientSocket);
clientList.add(multipleConnections);
multipleConnections.start();
}
// get client socket input out streams
clientInput = clientSocket.getInputStream();
clientoutput = clientSocket.getOutputStream();
// write to the client socket
clientoutput.write((message).getBytes());
// attempt to read form the client but we never receive any messages
BufferedReader br = new BufferedReader(new InputStreamReader(clientInput, ENCODING));
String inputLine;
String returnMessage;
String msg = br.readLine();
System.out.println(br.readLine());
while ((inputLine = br.readLine()) != null && inputLine != "") {....do stuff
Any input appreciated.
After a week of trying just about ever possible solution out there I found that appending a return carriage and a new line character to every message the client sent to the server via an outputtsteam did the trick.
private static final String CRLF = "\r\n"; // newline
try {
outputStream.write((text + CRLF).getBytes());
outputStream.flush();
} catch (IOException e) {
e.printstacktrace();
}
I am not sure why this worked so anyone out there that could shed light on this would be great. I am using java swing in eclipse on Windows 10 OS.
I have read through most similar questions in Stack-overflow . But i can't find similar one.
I build one client and one server. For my client networking, i build a class which contains a socket and many relevant methods like this :
public class Connector {
private Socket socket;
private DataOutputStream output;
private DataInputStream input;
public Connector(int x) throws UnknownHostException, IOException{
socket=new Socket("localhost",x);
}
public boolean isConnected(){
return socket.isConnected();
}
public void sendInfo(String str) throws IOException{
output = new DataOutputStream(socket.getOutputStream());
output.writeUTF(str);
output.flush();
}
public String receiveInfo() throws IOException{
input = new DataInputStream(socket.getInputStream());
return input.readUTF();
}
public boolean loginSuccess() throws IOException{
input = new DataInputStream(socket.getInputStream());
return input.readBoolean();
}
}
and when my client runs(the server run in my IDE),
String userAccount = "VerifyAccount" + "#" + userNametf.getText() + "#" + passwordtf.getText() + "#" + i;
connector.sendInfo(userAccount);
if(connector.isConnected())
System.out.println("the connector is still connected!");
else
System.out.println("the connector is no connected!");
if(connector.loginSuccess()){
System.out.println("Log in success");
}
else;
and this is my server:
ServerSocket serverSocket = new ServerSocket(8000);
while(true){
Socket socket = serverSocket.accept();
Thread thread = new Thread(()->{
try{
DataInputStream input = new DataInputStream(socket.getInputStream());
DataOutputStream output = new DataOutputStream(socket.getOutputStream());
String tempStr = input.readUTF();
System.out.println("Server receive data : "+tempStr);
String[] tempStrArray = tempStr.split("#");
if(tempStrArray[0].equals("VerifyAccount")){
if(UserVerification.isValid(tempStr.substring(14))==1){
output.writeBoolean(true);
output.flush();
}
else{}
}
else if(tempStrArray[0].equals("RegisterAccount")){}
else{}
}
catch(IOException ex){
ex.printStackTrace();
}
});
thread.start();
}
So the whole process is that the client socket connects to the server socket ,
then client send one string to the server , the server process the string , and write a boolean value back to the client , but when i call connector.LoginSuccess() , the compiler will throw an exception like this:enter image description here
You are never closing the accepted socket. You are also attempting to read a boolean that may never be sent. And, as I said in comments, isConnected() doesn't do what you think it does: it doesn't magically start returning false when the peer disconnects.
Hello stackoverflow community,
i am stuck at a problem regarding socket communication in Java.
Here is the sample code of my Server and Client class:
Server:
public class OTPServer {
static ServerSocket serverSocket;
final static int PORT = 4242;
static Socket clientConnection;
public static void main(String[] args) {
try {
serverSocket = new ServerSocket(PORT);
System.out.println("Socket initialized");
String serverMessage = "Hello, I am the Host";
ServerTool serverTool = new ServerTool();
while (true) {
clientConnection = serverSocket.accept();
if(clientConnection.isConnected()) {
System.out.println("Client connected");
}
BufferedReader clientInputReader = new BufferedReader(new InputStreamReader(clientConnection.getInputStream()));
DataOutputStream serverOutput = new DataOutputStream(clientConnection.getOutputStream());
System.out.println("Sending message to client: " + serverMessage);
serverOutput.writeBytes(serverTool.encodeMessage(serverMessage));
serverOutput.flush();
String clientMessage = clientInputReader.readLine();
System.out.println("Encoded answer from client: " + clientMessage);
String decodedMessage = serverTool.decodeMessage(clientMessage);
System.out.println("Decoded answer from client: " + decodedMessage);
serverOutput.close();
clientInputReader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Hello, I am the OTP Server!");
}
Here is the Client:
public class OTPClient {
static Socket clientSocket;
final static int PORT = 4242;
final static String HOST = "localhost";
public static void main(String[] args) {
System.out.println("I am the OTP Client!");
String serverMessage;
String clientResponse = "I am the Client";
OTPTool otpTool = new OTPTool();
try {
clientSocket = new Socket(HOST, PORT);
BufferedReader serverInput = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
DataOutputStream outputStream = new DataOutputStream(clientSocket.getOutputStream());
System.out.println("Connection to Host established");
serverMessage = serverInput.readLine();
System.out.println("Encoded Message from Server: " + serverMessage);
String decodedMessage = otpTool.decodeMessage(serverMessage);
System.out.println("Decoded message from Server: " + decodedMessage);
System.out.println("Answering with own message: " + clientResponse);
outputStream.writeBytes(clientResponse);
outputStream.flush();
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Now where is my problem:
The connection establishes and the Server seems to send its message to the client and waits for a answer. The Client does not print the message he got from the Server.
As soon as i cancel the Server the client prints the message it gets from the server as well as the information, that the answer is send end exits with exit code 0 so it seems that this part is fine it just is stuck somehow.
I already tried to flush the outputStream as you see in the example code given.
Is there something obvious im missing?
I know, this is really basic stuff but its my first time using sockets for communication.
Thank you in advance!
Best Regards,
Ronny
Btw: i know that the server only connects to one client requesting a connection. Thats absolutely sufficient for my use.
It is getting stuck because serverInput.readLine(); blocks until either a line break or end of file is encountered. On the server side, you are not sending a line break, so the client blocks.
So I did this client server program in java for my college mini project. Note that this is just a small module of a big project I'm working on. I need a string to be sent from the client to the server. The server will return back the string as it is back to the client. (The code will be modified later such that the string is processed before sending back). The client will send a string whenever needed to the server. Thus it means it is compulsory for the server to be running for indefinite time.
The problem I face here is that my server works perfectly only for the first time when the client sends a string. If I run the client the second time with a different string, I get back the same string I sent to the server previously!
Here is my server program:
public class Server {
public static boolean x = true;
public static String reply;
public static void main(String a[]) throws Exception {
System.out.println("Entered server console..");
Socket echoSocket = null;
ServerSocket serverSocket = null;
PrintWriter out = null;
BufferedReader in = null;
System.out.println("Initializing Connection..");
boolean runFlag = true;
try {
serverSocket = new ServerSocket(77);
while (runFlag) {
echoSocket = serverSocket.accept();
out = new PrintWriter(echoSocket.getOutputStream(), true);
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
while (x) {
in = new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));
reply = in.readLine();
if (reply != null) {
x = false;
}
}
System.out.println("received: " + reply);
out.println(reply);
System.out.println("sent back: " + reply);
stdIn.close();
}
} catch (Exception e) {
System.out.println("Exception in starting server: " + e.getMessage());
} finally {
out.close();
in.close();
echoSocket.close();
}
}
}
Here is my Client program:
public class Client {
public static String reply,temp;
public static boolean x=true;
public Client()
{
temp="lala";
}
public Client(String t)
{
temp=t;
}
public static void main(String[] args) throws IOException {
Socket echoSocket = null;
PrintWriter out = null;
BufferedReader in = null;
try {
echoSocket = new Socket("localhost", 77);
out = new PrintWriter(echoSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));
} catch (UnknownHostException e) {
System.err.println("Don't know about host: localhost.");
System.exit(1);
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to: localhost.");
System.exit(1);
}
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
temp="lala"; //this is the string to be sent
out.println(temp);
while (x) {
reply= in.readLine();
if(reply!=null)
{
x=false;
}
}
System.out.println("reply: "+reply);
out.close();
in.close();
stdIn.close();
echoSocket.close();
}
}
Can anyone help me find what the problem here is?
while (x) {
in = new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));
reply = in.readLine();
if (reply != null) {
x = false;
}
}
Your server enters this loop the first time a client connects, and it sets the reply String to some input from the client. However, it never enters this loop again, as x's value never changes back to true.
When you accept a request, the x will be set false and never become true.
Please initial the x when you enter the loop.
What's more,if you use a socket between client and server, please move the
echoSocket = serverSocket.accept();
out of the first loop.And you can use echoSocket to communicate.Then you will
keep the long connection.
been trying to figure this problem out for about 5 hours but cant seem to see it, although all the steps are done to send data, I can only receive messages to the server, but not from server to client. I'm in the early stages of building/learning how to do a chat client program in command line. The following is the server code:
The CServer class:
public class CServer {
private static int port=2008, maxConnections=0;
private static String shutDownServer = "no";
public static void main(String[] args) throws IOException{
ServerSocket listen = new ServerSocket(port);
Socket server;
while(shutDownServer.equalsIgnoreCase("no")){
doComm connection;
System.out.println("\nWaiting for clients to connect...");
server = listen.accept(); // accept incomming connections from client
System.out.println("Client connected. Location: " + server.getInetAddress().getHostName());
connection = new doComm(server);
Thread thread = new Thread(connection);
thread.start();
}
}
public void shutDownServer(String command){
this.shutDownServer = command;
}
}
Now the doComm class that handles each client in thread:
public class doComm implements Runnable{
Socket server;
private String clientData;
public doComm(Socket server){
this.server = server;
}
public void run(){
try {
BufferedReader fromClient = new BufferedReader(new InputStreamReader(server.getInputStream()));
DataOutputStream toClient = new DataOutputStream(server.getOutputStream());
clientData = fromClient.readLine();
System.out.println("Client sent: "+clientData);
(( The problem -imo- may be either this statement: ))
toClient.writeBytes("Recieved your sentence '"+clientData+"' and more to come :)!");
//server.close();
} catch (IOException e) {
System.out.println("IOException on socket listen: " + e);
e.printStackTrace();
}
}
}
Now the client class CClient:
public class CClient {
static String address = "localhost";
static int port = 4444;
static Socket echoSocket;
public CClient(int port, String addr){
changePort(port);
changeAddr(addr);
}
public static void main(String[] args) throws IOException, UnknownHostException{
Scanner scan = new Scanner(System.in);
System.out.println("Please enter the port to connect to: ");
int temp_port = Integer.parseInt(scan.nextLine());
System.out.println("Please enter the address of server: ");
System.out.flush();
String temp_addr = scan.nextLine();
CClient client = new CClient(temp_port,temp_addr);
PrintWriter out = null;
BufferedReader in = null;
try{
System.out.flush();
echoSocket = new Socket(address,port);
out = new PrintWriter(echoSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));
}
catch(IOException e){
System.err.println("IOException error: " + e.getStackTrace());
}
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
String userInput;
while ((userInput = stdIn.readLine()) != null) {
out.println(userInput);
System.out.println("thingy prints right after this...");
(( or here: ))
System.out.println("echo: " + in.readLine());
}
}
public void changePort(int port){
this.port=port;
}
public void changeAddr(String addr){
this.address=addr;
}
}
clientData = fromClient.readLine();
toClient.writeBytes("Recieved your sentence '"+clientData+"' and more to come :)!");
This is a very common problem whose root cause is the failure to document and specify the protocol being used for communication. Here you are receiving lines but sending bytes. If you had a protocol document, it would either specify that lines were exchanged or that arbitrary units of bytes were exchanged. That would show that one of these lines of code is wrong, and you could fix it. But without a protocol specification, you can't even tell which side is wrong.
Please, take my advice from years of painful lessons -- document a protocol before you implement. Then, if it doesn't work, you can follow this three step process:
Does the client follow the documented protocol? If not, it is broken.
Does the server follow the documented protocol? If not, it is broken.
The protocol specification is broken.
In this case, the protocol specification would document what constitutes a "message" for your protocol. It would then be each side's responsibility to send complete messages and find these message boundaries on receive. However, in your case, one piece of code expects a line terminator to mark a message boundary and the other side doesn't send one.
Is the sender wrong to omit a message boundary? Is the receiver wrong to insist on receiving one? Nobody knows because there's no specification to say what's the right thing to do.