I have TCP server-client application. It works but sometime something happens. Client connects to server but server says he doesn't accepted him.
Server side code:
while(!stopped){
try {
AcceptClient();
} catch(SocketTimeoutException ex){
continue;
} catch (IOException ex) {
System.err.println("AppServer: Client cannot be accepted.\n"+ex.getMessage()+"\n");
break;
}
...
private void AcceptClient() throws IOException {
clientSocket = serverSocket.accept();
clientSocket.setSoTimeout(200);
out = new ObjectOutputStream(clientSocket.getOutputStream());
in = new ObjectInputStream(clientSocket.getInputStream());
System.out.println("Accepted connection from "+clientSocket.getInetAddress());
}
Client side code:
try {
socket = new Socket(IPAddress, serverPort);
socket.setSoTimeout(5000);
out = new ObjectOutputStream(socket.getOutputStream());
in = new ObjectInputStream(socket.getInputStream());
} catch (IOException e1) {
sendSystemMessage("DISCONNECTED");
sendSystemMessage(e1.getMessage());
return;
}
sendSystemMessage("CONNECTED");
If client connects the message:
Accepted connection from ... appears. But sometimes it doesn't appear
even if client sends message "CONNECTED"
Server is still runing the loop trying to get client and it is catching socketTimeoutException. Client is connected, sends message and waits for response.
I suspect a missing 'flush' inside your client's 'sendSystemMessage()'.
Unfortunately the constructor of ObjectInputStream attempts to read a header from the underlying stream (which is not very intuitive IMHO). So if the client fails to flush the data - the server may remain stuck on the line "in = new ObjectInputStream(socket.getInputStream())"...
As a side note it's usually better for a server to launch a thread per incoming client, but that's just a side remark (plus it obviously depends on requirements).
I found the problem. The communication on my net is too slow so it timeouts in getting inputstream. The solution has two parts. Flushing outputstream before getting inputstream. And set socket timout after streams are initialized.
serverside:
clientSocket = serverSocket.accept();
out = new ObjectOutputStream(clientSocket.getOutputStream());
out.flush()
in = new ObjectInputStream(clientSocket.getInputStream());
clientSocket.setSoTimeout(200);
Related
I would like to run a combination of Dart and Java code, that can communicate with each other.
Therefore I chose to go with sockets, with the server socket written in Java and the client socket written in Dart.
This is the code I wrote:
Server
ServerSocket server = new ServerSocket(12345);
server.setSoTimeout(0);
System.out.println("waiting for connection...");
while (true) {
try {
Socket client = socket.accept();
DataInputStream input = new DataInputStream(client.getInputStream());
DataOutputStream output = new DataOutputStream(client.getOutputStream());
System.out.println("connected to " + client.getLocalSocketAddress() + ".");
while (true) {
output.write(input.readLine());
}
} catch (IOException e) {
System.out.println("disconnected.\n\nwaiting for connection...");
}
}
Client
Socket client = await Socket.connect('localhost', 12345);
client.write('hello there\n');
client.close();
Unfortunately the server does not receive the ping message sent by the client.
By now I suppose, that the problem lies in the Dart code, because when executing a client written in Java worked just fine.
Do you know, how to solve this? If so, please let me know ho. Thank you in advance!
Please note:
As there will never be more than one client at a time, I chose to go with this approach. I am aware, that normally this is no good style.
In the documentation for close() on the Socket class:
NOTE: Writes to the IOSink may be buffered, and may not be flushed by a call to close(). To flush all buffered writes, call flush() before calling close().
https://api.dart.dev/stable/2.7.1/dart-io/Socket/close.html
I do not know why, but it seems that the problem lies in the DataInputStream/DataOutputStream.
Here is what worked:
Server
ServerSocket server = new ServerSocket(12345);
server.setSoTimeout(0);
System.out.println("waiting for connection...");
while (true) {
try {
Socket client = socket.accept();
BufferedWriter output = BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
BufferedReader input = new BufferedReader(new InputStreamReader(client.getInputStream()));
System.out.println("connected to " + client.getLocalSocketAddress() + ".");
while (true) {
output.writeUTF(input.readUTF());
}
} catch (IOException e) {
System.out.println("disconnected.\n\nwaiting for connection...");
}
}
Client
Socket client = await Socket.connect('localhost', 12345);
client.write('hello there\n');
client.close();
This is working for me.
Socket client = socket.accept();
byte[] b = new byte[100];
client.getInputStream().read(b);
System.out.println(new String(b));
I have written a code in java to interface my computer with a transmitter a transmitter device, with a communication board already implemented and ready to connect via TCP/IP to any server with a specific address IP (say 192.168.2.2) and listening to a specific port number (say 4000).
I followed the exact strep how to create a server side application in Java offering a that listening port, so that I can connect to that transmitter.
I don't understand why when I try to debug the code, it blocks a the line clientSocket = serverSocket.accept(), and throws a timeout exception.
Could someone help me find out where the error might be in my code?
Any help would be greatly appreciated.
Thanks.
Here is the code:
public class Server {
public static void main(String[] args) {
// TODO Auto-generated method stub
//Declares server and client socket, as well as the input and the output stream
ServerSocket serverSocket = null;
Socket clientSocket = null;
PrintWriter out;
//BufferedReader in;
BufferedReader in;
try{
InetAddress addr = InetAddress.getByName("192.168.2.2");
//Opens a server socket on port 4000
serverSocket = new ServerSocket(4000) ;
//Sets the timeout
serverSocket.setSoTimeout(30000);
System.out.println("Server has connected");
//Create a connection to server
System.out.println("Server listening connection from client ....");
//Listens and waits for client's connection to the server
clientSocket = serverSocket.accept();
// Creates input and output streams to socket
out = new PrintWriter(clientSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
//Reads response from socket
while((in.readLine())!= null ){
System.out.println ( in.readLine() );
}
System.out.println ( "Closing connection ....");
//Terminates connection
clientSocket.close();
serverSocket.close();
System.out.println("Connecton successfully closed");
}
catch(IOException e){
System.out.println(e);
}
}
}
Could someone help me find out where the error might be in my code?
There is no error in your code that could cause this problem. Clearly you haven't configured the device to connect to this server correctly, or the device isn't running, or it isn't connecting, or there is a firewall in the way. Investigate that.
However:
InetAddress addr = InetAddress.getByName("192.168.2.2");
What is this for? It isn't used.
System.out.println("Server has connected");
This is simply not true. The server hasn't connected. At this point all it has done is create a listening socket.
while((in.readLine())!= null ){
Here you are reading a line and throwing it away.
System.out.println ( in.readLine() );
Here you are printing every second line, having thrown every odd line away. The correct way to write this loop is:
String line;
while ((line = in.readLine()) != null)
{
System.out.println(line);
}
Note also that this server will service exactly one client and then exit. There should be a loop around everything from accept() to clientSocket.close(), and if there are multiple devices it should start a new thread per accepted socket to handle the I/O.
You specified timeout of 30 seconds, didn't you? :
serverSocket.setSoTimeout(30000);
So after 30 seconds, no matter whether stopped in debugger or running, this will timeout and throw exception.
So I've been trying to figure out how to send messages between my arduino and my java servlet (tomcat) and have been bumping into some problems. I'm using this code in my java servlet:
ServerSocket server;
//socket server port on which it will listen
int port = 9876;
String message = "";
//create the socket server object
server = new ServerSocket(port);
System.out.println("Server socket created");
//keep listens indefinitely until receives 'exit' call or program terminates
while(true){
System.out.println("Waiting for client request...");
//creating socket and waiting for client connection
Socket socket = server.accept();
BufferedReader buff = new BufferedReader(new InputStreamReader (socket.getInputStream()));
System.out.println("Input stream established");
message = buff.readLine();
System.out.println("Message Received: " + message);
buff.close();
socket.close();
//terminate the server if client sends exit request
if(message.equalsIgnoreCase("exit")) break;
}
System.out.println("Shutting down Socket server!!");
//close the ServerSocket object
server.close();
But it's hanging on the
Socket socket = server.accept();
line. I assume this is because the messages i'm sending from the arduino aren't arriving. On the arduino side of things, this is my client:
if (client.connect(ip, 9876)) {
Serial.println("connected");
client.println("12345678");
Serial.println("Message sent");
} else {
Serial.println("connection failed");
}
Not much to it. Now, I've tried sending this as a HTTP POST request, but without success (surely i'm doing it incorrectly, i just don't know how to do it, i've tried for a while). I know this is probably horrifically written, but i'm very open to learning from you guys today.
The weird thing is that this works exactly how i want it to when i put the java server code in a new regular java project. Can anyone help me figure this out? Why is it hanging in the servlet but not in a regular java project?
I have a big problem. I have developped a client-server application. A client thread sends a serialized object to the server and the server sends back a serialized object. Currently I'm using one server and 10 client threads and after about 30 seconds I get the error message from each client thread (IOException):
No buffer space available (maximum connections reached?): connect
If I'm looking in netstat then I see that there are a lot of connections created and it is growing and growing and all connections are in TIME_WAIT state.
I don't know why. I close the sockets in the server and in the clients everytime in a finally block. Here is some code:
In the server I have in socketHandlerThread:
ServerSocket serverSocket = new ServerSocket(port);
serverSocket.setSoTimeout(5000);
while(true) {
Socket socket = serverSocket.accept();
}
The new socket is then put on a LinkedBlockingQueue and a worker thread takes the socket and makes the following:
try {
outputStream = new ObjectOutputStream(new BufferedOutputStream(socket.getOutputStream()));
outputStream.flush();
inStream = new ObjectInputStream(new BufferedInputStream(socket.getInputStream()));
ClientRequest clientRequest = (ClientRequest) inStream.readObject();
...
outputStream.writeObject(serverResponse);
outputStream.flush();
} catch....
} finally {
if (inStream != null) {
inStream.close();
}
if (outputStream != null) {
outputStream.close();
}
if (socket != null) {
socket.close();
}
}
On the client side I have the following code:
try {
socket = new Socket(host, port);
outputStream = new ObjectOutputStream(new BufferedOutputStream(socket.getOutputStream()));
outputStream.flush();
inputStream = new ObjectInputStream(new BufferedInputStream(socket.getInputStream()));
outputStream.writeObject(request);
outputStream.flush();
Object serverResponse = inputStream.readObject();
} catch....
} finally {
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
if (socket != null) {
socket.close();
}
}
Can somebody help? I really don't know what mistake I made. I seems that the sockets get no closed but I don't know why.
Could it be the problem that I put the sockets on a queue on the server side so that the socket is somehow copied?
Edit: If I put the client and the server each on a different Amazon EC2 classic instance running Linux AMI then it works. Could it be a problem with Windows or is the problem simply that I was running the Clients and servers on the same machine (my local pc)?
Does somebody see a bug in my code?
Edit2: As said above on EC2 instances it works but if I use netstat it shows still a lot of lines saying TIME_WAIT.
Here are screenshots:
https://drive.google.com/file/d/0BzERdJrwWrNCWjhReGhpR2FBMUU/view?usp=sharing
https://drive.google.com/file/d/0BzERdJrwWrNCOG1TWGo5YmxlaTg/view?usp=sharing
First screenshot is from windows. "WARTEND" means "WAITING" (it is german).
The second screenshot is from Amazon EC2 (to the left the client machine, to the right the server machine).
TIME-WAIT is entered after the connection is closed at both ends. It lasts for a couple of minutes, for data integrity reasons.
If the buffer problem is due to TIME-WAIT states at the server, the solution is to make the server be the peer that first receives the close. That will shift the TIME-WAIT state to the client, where it is benign.
You can do that by putting your server-side request handling into a loop, so that it can handle multiple requests per connection, and so that the server only closes the socket when it reaches end of stream on it.
for (;;)
{
try
{
ClientRequest clientRequest = (ClientRequest) inStream.readObject();
...
outputStream.writeObject(serverResponse);
outputStream.flush();
}
catch (EOFException exc)
{
break;
}
}
If you then implement connection-pooling at the client, you will massively reduce the number of connections, which will further reduce the incidence of the buffer problem.
I created a java chat application (client and server)
Everything works fine when I'm on my LAN (using LAN IP address of the server into my client).
But when I'm using the Internet address of my server in my client, the strings are sent only when I close the output Data stream of my client (and all the strings are sent at once).
Here's a quick snap of my code (I have port forward from 6791 to 6790 in the example below),
My server (thread):
// this line is actually on my global server class, used below with theServer
ServerSocket svrSocket= new ServerSocket(6790);
//wait for incoming connection
connectionSocket = svrSocket.accept();
connectionSocket.setSoTimeout(10000);
// free the accepting port
svrSocket.close();
//create a new thread to accept future connections (creates a new svrSocket)
theServer.openNewConnection();
//create input stream
BufferedReader inFromClient = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
boolean threadRunning = true);
while (threadRunning) {
//System.out.println("thread: in the while");
try {
Thread.sleep(100);
clientSentence = inFromClient.readLine();
System.out.println(clientSentence);
}
catch...
}
My client:
InetAddress dnsName;
Socket clientSocket;
PrintWriter out;
dnsName = InetAddress.getByName("myAddress.me");
clientSocket = new Socket(dnsName.getHostAddress(), 6791);
Thread.sleep(10);
out = new PrintWriter(clientSocket.getOutputStream(), true );
int i=140;
while (i>130){
try {
out.println(Integer.toString(i));
out.flush();
Thread.sleep(200);
}
catch(Exception e) {
e.printStackTrace();
}
i--;
}
out.flush();
out.close();
clientSocket.close();
I've tried with DataOutStreams, there's nothing to do.
My server will only receive the strings when out.close() is called on client side.
Is there a reason why, over the Internet, the data stream has to be closed for data to be sent? Is there a way around this? Am I doing something wrong?