TCP client and server - java

I'm working on a project which expects a TCP client and Server, where server echoes the message back to client. Following is from the assignment:
The server application shall:
Listen for TCP connections on a well known IP address and port
Accept connections initiated on that port
Receive messages from the client and echo them back
Continue to do this until the client drops the connection.
The client application shall:
Establish a connection with the server at its well known IP address and port
Send messages in an asynchronous manner to the server. The format of the message is
of your choice; however, it must contain enough information in order for it to be
recognized on its return from the server.
I have completed the coding for Server, and this is what i've come up with for the client.
My questions:
What does it mean that Server listens for TCP connections on a well known IP and Port In my implementation, i've used ServerSocket which accepts the port server listens on. Did i interpret it correctly?
In my current implementation of TCPClient, client sends messages to Server, but the println() seems to be a blocking call, which makes it Synchronous. What can i do to make my client asynchronous?
For brevity, I havent added the code of TCPServer, let me know if it is needed
UPDATE**
Based on the feedback, i have modified by TCPClient class. After receiving client request, i spawn two threads ReceiveMessage and SendMessage. Doing that gives me following exception:
[Client] Message sent: Message from Client 97
[Client] Message sent: Message from Client 98
[Client] Message sent: Message from Client 99
[Client] Done Sending all the messages
java.net.SocketException: Socket closed
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:264)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:306)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:158)
at java.io.InputStreamReader.read(InputStreamReader.java:167)
at java.io.BufferedReader.fill(BufferedReader.java:136)
at java.io.BufferedReader.readLine(BufferedReader.java:299)
at java.io.BufferedReader.readLine(BufferedReader.java:362)
at org.chanders.client.ReceiveMessage.run(ReceiveMessage.java:18)
at java.lang.Thread.run(Thread.java:680)
Following is the new Client Code:
public class TCPClient {
Socket clientSocket = null;
OutputStream out = null;
BufferedReader in = null;
String message = "Hello from Client";
int messagecount = 100;
// server credentials
private static final String SERVER_ADDRESS = "localhost";
private static final int SERVER_PORT = 50001;
protected void execute() {
try {
clientSocket = new Socket(SERVER_ADDRESS, SERVER_PORT);
Thread send = new Thread(new SendMessage(clientSocket.getOutputStream()));
Thread receive = new Thread(new ReceiveMessage(clientSocket.getInputStream()));
send.start();
receive.start();
//For server to wait until send and receive threads finish
send.join();
receive.join();
} catch (UnknownHostException uhe) {
System.err.println("Couldnt find host: " + SERVER_ADDRESS);
uhe.printStackTrace();
System.exit(-1);
}catch(IOException ioe) {
System.err.println("Couldnt get I/O: " + SERVER_ADDRESS);
ioe.printStackTrace();
System.exit(-1);
}catch(InterruptedException ie) {
System.err.println("Thread.join failed: ");
ie.printStackTrace();
System.exit(-1);
}
finally {
//cleanup();
}
}
private void cleanup() {
try {
clientSocket.close();
}catch(Exception e) {
e.printStackTrace();
System.exit(-1);
}
}
public static void main(String[] args) {
TCPClient client = new TCPClient();
client.execute();
}
public class SendMessage implements Runnable {
OutputStream out = null;
String message = "Message from Client";
int messageCount = 100;
public SendMessage(OutputStream out) {
this.out = out;
}
public void run() {
PrintWriter writer = new PrintWriter(out);
try {
for (int i = 0; i < messageCount; i++) {
String m = message + " " + i;
writer.println(m);
System.out.println("[Client] Message sent: " + m);
}
System.out.println("[Client] Done Sending all the messages");
} catch (Exception e) {
e.printStackTrace();
System.exit(-1);
} finally {
cleanup();
}
}
private void cleanup() {
try {
out.close();
}catch(Exception e) {
e.printStackTrace();
System.exit(-1);
}
}
}
public class ReceiveMessage implements Runnable {
InputStream in = null;
String message;
public ReceiveMessage(InputStream in) {
this.in = in;
}
public void run() {
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
try {
while ((message = reader.readLine()) != null) {
System.out.println("[Client] Received message from Server: "
+ message);
}
System.out.println("[Client] Done Receiving messages from Server");
} catch (Exception e) {
e.printStackTrace();
} finally {
cleanup();
}
}
private void cleanup() {
try {
in.close();
}catch(Exception e) {
e.printStackTrace();
System.exit(-1);
}
}
}

In this context, Asynchronous probably doesn't mean that you can't use println, but that the client must be able to recevie messages while it's sending new ones.
The client should create the socket and then create two threads, one to send messages and the other to recive and print them.
Update
To avoid the exception, use clientSocket.shutdownOutput() instead of closing the output stream.
You could move the send code back to the main thread and keep a separate thread for the receive code or call shutdownOutput() after joining the send thread. Whatever works better for you.

Use a separate thread for each client. When you write something, in the server end , there must be a method which accepts the string. Otherwise it will be blocking. Paste your server code.

Well known ports are port numbers that have been specifically designated for particular protocols, for example 80 is for HTTP and 443 is for HTTPS. Are you meant to be implementing a particular protocol? If you are I would suggest you use the port number for that protocol. Wikipedia has a list of well known port numbers here:
http://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers

If this is a professional assignment (as opposed to a some homework) then I would strongly recommend the Netty Server, which is basically a NIO client server framework. It significantly simplifies/streamlines the development of this sort.
Make sure to check their documentation as it provides examples implementing exactly the server/client functionality stated in the question.
If this is a homework then this example should provide all necessary details. Please also check Oracle resources.

Related

How to stop Java Socket client keeps sending 'null' data?

I created 2 Java programs with sockets in it. I want the client to send continuous data to the server. But after the message sent to the server, the client keeps sending 'null' value to the server (it happens when I close the socket in client program).
Here is my codes:
import ...
public class MainClient {
private Socket serverSock;
private PrintStream clientOutput;
public static void main(String[] args) {
MainClient client = new MainClient();
client.runClient();
}
public void runClient() {
try {
serverSock = new Socket("127.0.0.1",8282);
clientOutput = new PrintStream(serverSock.getOutputStream());
clientOutput.println("Hello, I'm Connected.");
for (int i=0;i<5;i++) {
clientOutput.println(i + "");
clientOutput.flush();
}
} catch (IOException e) {
e.printStackTrace();
}finally {
// try {
// serverSock.close(); It will keeps sending 'null' data to the server if I use this line.
// } catch (IOException e) {
// e.printStackTrace();
// }
}
}
}
The Server Side:
public class MainServer {
private ServerSocket serverSocket;
private int listenPort = 8282;
private InputStream inps;
private Socket clientSocket;
private BufferedReader clientInput;
private MainServer() {
String clientMsg = "";
try {
serverSocket = new ServerSocket(listenPort);
System.out.println("Server is Listening on " + listenPort);
clientSocket = serverSocket.accept();
clientInput = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
while(clientSocket.isConnected()) {
clientMsg = clientInput.readLine();
System.out.println("Client : " + clientMsg);
}
}catch(IOException ex) {
ex.printStackTrace();
}finally {
try {
clientSocket.close();
} catch (IOException e) {}
}
}
public static void main(String[] args) {
new MainServer();
}
}
I tried to close the OutputStream on the Client side with clientOutput.close(); but it sends nulls to the server after it sends the 0-4 loop.
To make it stop and avoid the client sends null data, i should not insert the serverSock.close(); on the Client, but it will returns SocketException. I wanted the client to send 'Closed' message after its done.
Summary, the output on the server is:
Client: 0
Client: 1
Client: 2
Client: 3
Client: 4
Client: null
Client: null
//And so on..
I think there is something missing on the Client Program, i guess?
Thank you for the help :)
As the comment noted, the client is not sending a null value.
The isConnected() method does not do what you think it does, namely it does not tell you if the socket is currently "connected" to its peer, at least in the way you think it should. isConnected() becomes true as soon as the socket transitions into the connected state, and stays true thereafter, even after the socket is shutdown. See this discussion and others on stackoverflow.
The correct way to determine if the peer has shutdown the connection is to attempt to read from the socket and then examine the result for evidence of closure. Please read the Javadocs for the method you are using, they will tell you what the various return values mean. For the BufferedReader.readLine() method, it says:
Returns:
A String containing the contents of the line, not including
any line-termination characters, or null if the end of the stream has
been reached
Throws:
IOException - If an I/O error occurs
Thus you need to check for a null return value to detect a normal socket closure, and if you receive an IOException that indicates some kind of network anomaly.
Your MainClient() have no problem.
clientSocket.isConnected() function in MainServer() always check the status of the client and which results an infinite loop, so after the message 'client:4', clientInput.readLine() should return 'null'.
So instead of checking the client socket is connected or not you can check the client socket is closed or not using function 'clientSocket.isClosed()'.
replace the while loop in MainServer() with below code,
while(!clientSocket.isClosed()) {
clientMsg = clientInput.readLine();
System.out.println("Client : " + clientMsg);
if(clientMsg.equals("Closed")){
clientSocket.close();
// serverSocket.close();
}
}
this will help you to close the client socket at the time of receiving 'Closed' message from server and this avoid the infinite execution of while loop as well as null statement printing.
The code "serverSocket.close()" help you to close the server socket and you can use this at 'MainServer()' if you need to stop the port listening.
typically the code should be something similar
private MainServer() {
String clientMsg = "";
try {
serverSocket = new ServerSocket(listenPort);
System.out.println("Server is Listening on " + listenPort);
clientSocket = serverSocket.accept();
clientInput = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
while ((clientMsg = clientInput.readLine()) != null) {
if(isTerminationString(clientMsg)) {
break;
}
System.out.println("Client : " + clientMsg);
}
} catch (IOException ex) {
ex.printStackTrace();
} finally {
try {
clientSocket.close();
} catch (IOException e) {
}
}
}
boolean isTerminationString(String msg) {
return msg.equals("DONE!");
}
where in isTerminationString you check if the msg is a termination msg, the communication protocol should be shared between the client and the server . i gave the example of sending
a DONE message, but it could more complex than that .
as closing the close method on the socket does not guarantee that the socket on the other part gets closed as well, using the isClosed method might not be effective and results in the same problem you have .

what happens to a message when it gets to a server without reading stream in java?

If I have a server and a client and I opened a socket between the two:
1.Is it possible that the client will have a printWriter stream, in order to write things to the socket, but the server won't have in the mean time a bufferReader?
If the answer of 1 is yes, if that client will send a message to the server (who currently doesn't have a reading stream), what will happend to this message until te server will create a reading stream and read the message?
thank you
This is not at all specific to Java, but TCP/IP. There are buffers to keep the data received, so it's not possible that some data would be lost because one end isn't "ready" yet. This is because TCP will retransmit data that hasn't been acknowledged as received, guaranteeing that all the bytes that are written are received on the other (barring obvious cases).
in addition to #Kayaman's answer:
consider this Compile-able simple Java implemented example:
Server Side:
import java.io.*;
import java.net.*;
public class SimpleServer implements Runnable{
int serverPort = 45000;
ServerSocket serverSocket = null;
boolean isStopped = false;
public SimpleServer(int port){
this.serverPort = port;
}
public void run(){
try {
serverSocket = new ServerSocket(serverPort);
} catch (IOException e) {
System.err.println("Cannot listen on this port.\n" + e.getMessage());
System.exit(1);
}
while(!isStopped){
try {
Socket clientSocket = serverSocket.accept();
} catch (IOException e) {
// do nothing
}
}
}
public static void main(String[] args) throws IOException {
SimpleServer server = new SimpleServer(45000);
new Thread(server).start();
System.out.println("Server is waiting to connect");
}
}
Client Side:
import java.io.*;
import java.net.*;
public class SimpleClient {
public static void main(String[] args) throws IOException {
Socket socket = null;
PrintWriter out = null;
try {
socket = new Socket("127.0.0.1", 45000);
out = new PrintWriter(socket.getOutputStream(), true);
System.out.println("output stream created");
out.write(9);
System.out.println("message was sent to output with no listener");
} catch (UnknownHostException e) {
// do nothing
} catch (IOException e) {
// do nothing
}
}
}
the example is an implementation of a very basic client server connection in which a socket is created and a stream is defined only on the client side, followed by a write to the stream that will eventually be read by the server (if at all).
therefore, to answer you questions:
1) yes, it's possible to open a one-way connection stream without a "listener"
2) edit: according to #EJP: It will be saved within the socket's buffer until it is read or the socket is closed.

Strange behaviour of ServerSocket.accept method

I created class SocketListener to receive data through TCP protocol. My start method looks like this:
public void start() throws IOException {
LOGGER.log(Level.INFO, "SOCKET LISTENER STARTED PORT: " + port);
serverSocket = new ServerSocket(port);
while (true) {
FrameParser fp;
try {
socket = serverSocket.accept();
fp = new FrameParser(socket);
Thread thread = new Thread(fp);
thread.start();
} catch (Exception e) {
resetConnection();
}
}
}
Writing this code I based on example from oracle website (http://www.oracle.com/technetwork/java/socket-140484.html#server). When I placed line with serverSocket.accept() inside loop some of the packets was not received by ServerSocket. I am sure that this TCP packets was received on my network interface bacause I checked it later using Wireshark. I have no idea what causes that problem so I tried different things and I noticed that more packets was received when I change my code like this:
public void start() throws IOException {
LOGGER.log(Level.INFO, "SOCKET LISTENER STARTED PORT: " + port);
serverSocket = new ServerSocket(port);
socket = serverSocket.accept();
while (true) {
FrameParser fp;
try {
fp = new FrameParser(socket);
Thread thread = new Thread(fp);
thread.start();
} catch (Exception e) {
resetConnection();
}
}
}
I made this modification using trial and error method and unfortunately after this change my application started receive more data than I filtered in Wireshark (for example in Wireshark I saw 10 packets but my application created hundreds of new threads and it finished with out of memory error).
What can be a reason that in a first case not all of TCP packets reached to socket?

No response from second client socket

I am working with Java sockets. I have a server socket and two client sockets. My problem is, that the first client socket submits its message to my server socket, and the message from the second client socket is not arriving at the server socket. That means, that for the first client socket the while loop is interrupted after a succesful message, and the second client ends in an infinite while loop. If I test each client socket seperately in a test class, each client socket is submitting its message correctly to my server socket. By watching TCPView I noticed, that the client socket does not respond, as long as my port is used.
I read, that the second client socket should still respond its message, even if the port was used. In my case, the second client socket should always respond about a second after the first one. But I can't get them to work one after another.
So, here is my code for the method, which is waiting for client messages:
public void listenToSocket()
{
serverSocket = null;
thread = null;
SocketAddress adress = new InetSocketAddress(CommunicationValues.SOCKET_PORT);
try {
serverSocket = new ServerSocket();
serverSocket.setReuseAddress(true);
serverSocket.bind(adress);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
System.exit(0);
}
while(true){
try
{
Socket clientSocket = serverSocket.accept();
thread = new SocketMessageThread(clientSocket);
thread.start();
} catch (IOException e) {
System.out.println("MyServerSocket caught an error: \n" + e.getMessage());
e.printStackTrace();
}
}
}
This method is called in a thread. The structure looks like this:
SocketListenerThread calls the method listenToSocket() from class SocketListener
listenToSocket() is described above
The SocketMessageThread is handling the message output of the client socket in its run()-method.
EDIT
Here is the code of my SocketMessageThread:
public class SocketMessageThread extends Thread{
private Socket clientSocket;
private static int nameCounter = 0;
public SocketMessageThread(Socket clientSocket) {
this.clientSocket = clientSocket;
this.setDaemon(true);
this.setName("SocketMessageThread" + (nameCounter++));
}
public void run() {
try (
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));)
{
while (in.ready())
{
String inLine = in.readLine();
CommunicationValues.MESSAGE_MEMORIZER = inLine;
}
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}}
EDIT 2
Both clients only communicate with one particular message. E.g. when a client is started up, it mentioned, that the startup was successful with a single message. There are no repeating messages coming from the client sockets until the server sockets catches them. So if the server socket doesn't catch that one message, it's gone, and it won't be sent again by the client socket.
while (in.ready())
{
// ...
}
Classic misuse of ready(). Exchange all this for:
String inLine;
while ((inLine = in.readLine()) != null)
{
CommunicationValues.MESSAGE_MEMORIZER = inLine;
}
Presumably there is more code that you haven't shown us: otherwise all this will do is memorize the last line sent.

Sockets and Java chat

I'm new to java and i'm trying to learn how to use sockets.
I'm trying to write a simple text messenger, server - client, but i don't know how to make the server always listening for client's stream:
Here's the server code, by now it just manages 1 incoming connection, when the client connects, the server send a message to it:
import java.net.*;
import java.io.*;
public class SocketServer {
private InetAddress ServerAddress;
private int ServerPort;
private int ServerQueue;
private ServerSocket Server;
public SocketServer(String ServerAddress, int ServerPort, int ServerQueue)
{
try
{
this.ServerAddress = InetAddress.getByName(ServerAddress);
}
catch (UnknownHostException uhe)
{
uhe.printStackTrace();
}
this.ServerPort = ServerPort;
}
public boolean ServerCreate()
{
try
{
Server = new ServerSocket(this.ServerPort, 10, this.ServerAddress);
System.out.println("System Message: Server started!");
return true;
}
catch(IOException ioe)
{
ioe.printStackTrace();
System.out.println("System Message: Can't start server!");
return false;
}
}
public void ServerStartListening()
{
int exit = -1;
while(exit < 1)
{
try
{
Socket client = this.Server.accept();
OutputStream clientout = client.getOutputStream();
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(clientout));
bw.write("Welcome: "+client.toString());
bw.close();
}
catch (IOException ex)
{
ex.printStackTrace();
}
}
}
}
Sorry for my bad english.
You need to implement multi-threading in order to listen for multiple incoming requests. Refer this link: a very nice multi-threaded server example by oracle
You need to read sth. about threads. Here is an initial code:
ServerSocket socketListener;
DoSthWithThisSocket doSthWithThisSocketObj;
socketListener = new ServerSocket(LISTENINGPORT);
Socket socket;
Thread doSthWithThisSocketThread;
while (continueSocketListening()) {
socket = socketListener.accept();
doSthWithThisSocketObj = new DoSthWithThisSocket(socket);
doSthWithThisSocketThread = new Thread(doSthWithThisSocketObj);
doSthWithThisSocketThread.start();
}
There are two main options for doing multi-client socket servers in Java:
Start a new thread for each new client TCP connection as previous responders suggest. This is OK for smallish/toy servers, and when you are just starting playing with sockets. The big downside here is that this approach does not scale - just think about having a thousand concurrent clients ...
Use IO multiplexing with non-blocking sockets as provided by Java NIO package, dispatching accept/read/write events to registered callbacks. You can extend this with work-item queue(s) and a pool of pre-allocated worker threads to take advantage of multiple cores/CPUs in your hardware.

Categories

Resources