I have problem with my ClientListener, server send TCP package but Client do not display it.
Here is my code
https://github.com/Behoston/sieci/tree/master/src/tcp
(Server run new thread for each new client and this thread (to listen) and this thread run other to sending messages (it works - I can see messages in wireshark
Client run main thread where can input some text and second therad (not working properly) to listen messages from serever)
It's quite hard to answer your question if you only provide a link to your repository, some code snippets of the crucial classes or methods would be helpful.
If my understanding of the classes you provided is correct, this is the workflow you are trying to implement (correct me if I'm wrong):
Server gets started
Client connects
Server sends a welcome message (which is not getting displayed on clientside):
DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());
outToClient.writeBytes("Hello, your ID is: " + clientId + "; To send message please use 3 first chars to set target");
On the recieving side:
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
response = inFromServer.readLine();
As far as I see, you are waiting for a readLine() with your server sending a byteArray. Since readLine() waits for a line seperator (f.e. "\n"), your messages can't be processed.
Related
Prerequisites:
I'm using Xamarin to write a mobile app which should exchange small message chunks with a java server.
I'm using the .NET implementation of Bouncy Castle for sending data over TLS, since I'm restricted to a specific cipher suite (TLS_ECDH_anon_WITH_AES_256_CBC_SHA) which is not supported by default for Android phones above API Level 23.
The problem: If I only try to send data via the following code, everything is fine. But if I try to also read the response back, the stream hangs for some seconds and then throws the exception System.IO.IOException: Unable to read data from the transport connection: Operation on non-blocking socket would block. However, as you can see in the example below, I'm initializing Bouncy Castle's TlsClientProtocol with the "blocking"-constructor (docu says it is blocking if a stream is given), so the socket should not be non-blocking.
Furthermore, the server receives the data almost instantly, but only if no reading from the client will follow in code. If a .Read(..) or .DataAvailable check comes afterwards, the server receives the data after the exception occurred or it does not receive anything.
Purged/simplified code version:
Clientside Xamarin app:
TcpClient client = new TcpClient() { ReceiveTimeout = 5000, SendTimeout = 5000 };
client.Connect(ip, port);
NetworkStream stream = client.GetStream();
TlsClientProtocol protocol =
new TlsClientProtocol(stream, new Org.BouncyCastle.Security.SecureRandom());
protocol.Connect(new CustomTlsClient()); // CustomTlsClient derives from DefaultTlsClient and is used to overwrite the CipherSuite
protocol.Stream.Write(data, 0, data.length);
protocol.Stream.Flush();
// Sending won't work too if the following line is present
protocol.Stream.Read(buffer, 0, buffer.Length);
Server side java application (I have no access to it, but i got the info that it is implemented that way):
SSLServerSocket socket = (SSLServerSocket)SSLServerSocketFactory.getDefault().createServerSocket(port);
String[] enabledCipherSuites = new String[] { "TLS_ECDH_anon_WITH_AES_256_CBC_SHA" };
socket.setEnabledCipherSuites(enabledCipherSuites);
SSLSocket clientSocket = socket.accept();
clientSocket.startHandshake();
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
String request = in.readLine(); // Works only if the client won't read afterwards
out.println(request);
Some of the failed solution attempts so far:
Manually set client.Client.Blocking = false -- nothing changed
The exception says the socket is non-blocking, therefore I tried to wait in a loop via protocol.Stream.DataAvailable -- It was waiting forever, but after I quit the app, the server received the message (during the loop nothing was received by the server)
I wrote my own java server to test this behaviour on a localhost -- same results
I tried to use BeginSend / BeginRead -- same results
So, I'm actually starting to tear my hairs out of my head. Any help is appreciated!
EDIT: I fortunately found the solution, it was just a dumb error I made, see my answer below.
It turned out, that the exception message was somehow misleading. The socket was in blocking mode and the mistake was ... how should I call it ... dumb. I simply forgot to append a newline (\n). This was also the reason why the java server did not receive anything until the TcpClient was disposed - it was waiting for the newline.
I am trying to make a client send a request to a server and receive a response whilst keeping to connection up.
If i close the socket:
//server side
outToClient.writeBytes("Message to send");
connectionSocket.close();
//client side
serverResponse = inFromServer.readLine();
System.out.println("FROM SERVER: " + serverResponse);
Output on client side
FROM SERVER: Message to send
And after that the connection is lost, obviously.
If i do not close the socket:
//server side
outToClient.writeBytes("Message to send");
//client side
serverResponse = inFromServer.readLine();
System.out.println("FROM SERVER: " + serverResponse);
No output on client side.
The server never sends the message or the client never receives it.
Anyone knows a possible reason for this to be happening?
The client uses a thread to receive messages and a thread to send messages. The client socket is created in the main client thread so receiver and sender threads use the current socket to communicate.
Thanks in advance.
If the client expects to read a line, the server should write a line. A line is terminated by a \n character.
It may also be necessary to flush the stream you are using to send data to the client:
outToClient.writeBytes("Message to send\n");
outToClient.flush();
Without seeing the code it's hard to say if the flush is required or not.
Never, ever write any code on top of TCP without first specifying the protocol. Otherwise, when you have a problem like this, it's impossible to determine which end is at fault.
One side believes it's sending a "message". The other side does not believe the data it receives is a "message". Which is right? Well, if we had a protocol specification, we'd look at its definition of a "message" and see.
But we don't have one, so we can't say. This makes it impossible to construct a correct fix. If you change the sender to send a line, the receiver will still be broken in requiring a line. Or won't it? And you change the receiver to process messages that aren't lines, is that fixing it or breaking it?
It seems in this case that both sides are wrong. The most likely intent is that a message consists of a line of data terminated with a newline. The sender is not sending a newline and the recipient is not insisting on one either (because it accepts the data as a "message" when the connection closes). So unless the design intent really was that a "message" is a chunk of data not including a line ending terminated by either a line ending or the close of a connection, both sides are wrong.
Document the protocol. It's an essential step.
I am writing simple Server through TCP/IP for my android app.
I am facing a problem where server only receives messages after the timeout on the app.
My server side:
System.out.println("Connection accepted");
DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());
capitalizedSentence = "READY";
writeToUser(outToClient, "READY".getBytes());
String response = readFromUser(connectionSocket);
// Server hangs on readFromUser();
if(response.contains("IL"))
{
byte[] bytes = DatatypeConverter.parseHexBinary(foo);
writeToUser(outToClient, bytes);
}
App side:
if (ack.equals("READY")) {
ack = "";
dataOutputStream.writeBytes(command);
dataOutputStream.flush();
buf = new byte[556];
dataInputStream.read(buf);
// app hangs on read() and gets timeout
}
The problem is that, server receives command only after application gets read timeout.
My current scenario is this:
Connection accepted: Application receives "READY"
Application sends commands and tries to read response from server
Server is hanging on readFromUser() and only receives message after the app gets read timeout.
Any ideas what am I doing wrong ?
Update:
The code works if I use readLine, instead of read(buf) ( if I understand clearly server hangs on read(buf) and is in waiting mode as socket is not closed yet even though no more data is beeing sent. )
However such way I have to add "\n" after each command, and server is only emulator, app works with different device who does not understand "\n" at the end and will crash.
Is there any way I could make this work without using readLine() ?
Update 2
public void writeToUser(DataOutputStream outToClient, byte[] bytes) throws IOException
{
outToClient.write(bytes);
outToClient.flush();
String s = new String(bytes);
writeLog("Sent to client: " + s);
}
public String readFromUser(Socket socket) throws IOException, InterruptedException
{
writeLog("Reading...");
BufferedReader inFromClient = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String clientSentence = inFromClient.readLine();
writeLog("Received: " + clientSentence);
return clientSentence;
}
Above readFromUser() method works just as expected. But, this requires adding "\n" on each command sent from client app. And real device I have to communicate with does not understand "\n" and will treat the command as unrecognized... I am writing this server simply for testing purposes and I want it to be as close to real one as possible.
Previously I was just trying to get it done without "\n" on each command using inFromClient.read(cbuf); instead of readLine() and server always got hung on read, and received command only after socket was closed on client side. Even though I know that client sent the command and is waiting for response.
The question is how can I receive command without using readLine(); and "\n" on client side.
'how can I receive command without using readLine(); and "\n" on client side'. If you do not, or can not, want to use "\n" as a command terminator, then you must use another protocol to identify the start and end of the 'command' within the TCP octet/byte stream.
What protocol does your 'real device' server use to identify the start and end of commands? If it uses a byte-by-byte state-machine to identify a valid command then you are going to have to duplicate that in your test server.
You're reading lines but you aren't writing lines. So readLine() blocks until a line terminator arrives or the peer closes the connection.
Append a \n.
Why not you increase timeout from APPs side. Or you can write a thread that will hit server in some interval for some time and if no response then show time out. This problem is in Apps side.
I have a c++/windows program that receives data from another c++ program via a WM_COPYDATA message. It is then supposed to use Sockets/winsock to send this message on to a server written in Java. The client connects to the server fine, but it doesn't seem to be able to send messages in a timely fashion. However, once the client is closed down, all the messages it should have been sending get sent in one big lump. Here is an example of the terminal output of the Java server:
Server Starting up.
Client Accepted.
hi from clienttesttesttesttesttesttesttesttesttesttesttesttesttesttest
the first two lines are output by the Java server when those events happen. The last line is messages from the client. The client sends "hi from client" right after winsock is initialized, and then "test" at various points later in the program as it receives data from the other c++ program via WM_COPYDATA messages.
Here is the Java server code:
BufferedReader in = new BufferedReader(new InputStreamReader(
clientSocket.getInputStream()));
String incomingLine;
while((incomingLine = in.readLine()) != null)
System.out.println(incomingLine);
Here is the c++ function where the messages are sent:
void sendDataWinsock(char* text){
int result = send(ConnectSocket,text,(int)strlen(text),0);
}
And here is a section of WndProc where the WM_COPYDATA messages are processed:
case WM_COPYDATA:
sendDataWinsock("test");
break;
Does anyone know why it is doing this? It is as if the client program is adding all these messages to a queue of things it should be sending, but is too busy to send them immediately, and so only sends them as the program is closing down, when it no longer has to process Windows messages. Or, I suppose, the error could actually be in the Java code - I am fairly new to this.
You are reading lines on the server, but you are not sending lines.
That means your server sits there, receiving data but waiting to return a line of text back to your program from readLine() , which does not happen since no newlines , \n, gets sent. When the client exits, readLine() gives you back the data it read thus far.
I have the following Java socket client app, that sends same string to socket server:
import java.net.*;
import java.io.*;
public class ServerClient {
public static void main(String[] args) throws IOException {
System.out.println("Starting a socket server client...");
Socket client = new Socket("XXX.X.XXX.XX", 12001);
BufferedOutputStream stream = new BufferedOutputStream(client.getOutputStream());
String message = "ABC";
BufferedReader inputReader = new BufferedReader(new InputStreamReader(System.in));
String input = null;
while ( true ) {
System.out.print("Would you like to send a message to Server? ");
input = inputReader.readLine();
if ( !input.equals("Y") ) break;
System.out.println("Message to send: " + message);
System.out.println("Message length is: " + message.length());
byte[] messageBytes = message.getBytes("US-ASCII");
stream.write(messageBytes, 0, messageBytes.length);
stream.flush();
}
System.out.println("Shutting down socket server client...");
stream.close();
client.close();
inputReader.close();
}
}
The first time message is sent, server receives the message; however, every subsequent time I'm trying to send this message, server is not receiving anything. Message simply disappears. I am writing to the socket successfully (no exceptions) but nothing is coming on the other side of the pipe (or so I'm told).
I do not have access to the server app, logs or code, so I'm wondering if there is any approach you can recommend to figure out why server is not receiving subsequent messages. Any ideas would be greatly appreciated!
Clarification:
New lines are not expected by the server; otherwise, how would it even receive message the first time? As a trial and error, I did try sending '\n' and "\r\n" and 0x00 characters at the end of the string - all without any luck.
I thought flushing was an issue, so I tried various outputstream classes (PrintStream, PrintWriter, FilterOutputStream), but was still running into same exact issues. Then, if "flushing" is an issue, how is it working the first time?
Other tests:
1 - use a network sniffer to see what is realy hapening on the network
2 - use some program like TCP Test Tool to send data to the server and simulate your program. (netcat can also be used, but it sends a newline after each line)
Remember:
TCP is stream oriented. not message oriented.
One write on the client could take several reads on the server to .. read
Multiple writes on the client could get read by the server in one read
You'll hardly see the above scenarios in a test application on a local network, you will see them very quick in a production environemnt, or when you start to really speed up the sending/receiving.
Following this, if you are sending messages you need a delimiter, or some other way of indicating 'here's one message', e.g. defining the protocol to be 'the first byte is the length of the following message'.
And you'd need to check the receiving end wether it read a partial message, a whole message, and any combination thereof (e.e.g one read might have read 3 and a half message..).
A quick solution for your test app, write lines. That is, a string followed by a newline character. A bufferedreader's ReadLine() could then take care of the reassembly for you on the receiving end.
It works correctly here... but I am missing a carriage return or some other end of message after sending the message.
Hard to write more without knowing what the server expects (protocol)...
Maybe you should try something like
String message = "ABC\n";