Java TCP server - android client packet loss - java

I'm trying to create a basic multiplayer game for android, using a Java TCP server and Android client. The problem is slow speed when sending TCP packets. When I put Thread.sleep(100) then it works.
server side:
for(int i = 0; i<50; i++) {
client.send("test_" + i);
}
client just received (~3 packet)
test_0
test_1
server with sleep:
for(int i = 0; i<50; i++) {
client.send("test_" + i);
Thread.sleep(100);
}
client received ~45
EDIT: client side:
while (true) {
if (!running)
break;
inFromServer = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"), 2 * 1024);
String rawRecervied = inFromServer.readLine();
if (rawRecervied == null) {
close();
break;
}
final String recervied = rawRecervied.substring(2); // for skip utf bom chars
new Thread() {
public void run() {
listener.dataRecervied(recervied);
Log.e("TCP recervied", recervied); // debug
}
}.start();
}

Maybe the key is in the BufferedReader. You're in a loop, and constantly create a BufferedReader to check if something has been sent from the server. Once data is detected, you start processing it, but data keeps coming, and is buffered in the BufferedReader. After processing the initially detected data, you create again a BufferedReader but, what happens with all the data that was already buffered in the BufferedReader created before? Maybe it's lost.
Could you try creating the BufferedReader outside the loop?

If it is a one-way protocol where packet loss is acceptable then use UDP instead of TCP as it is cheaper in terms of network resources. I think this is not your case however. If TCP, then implement a basic flow control where the client acknowledges the received packet with echoing its ID back to the server.
You should also revise your client and server code because this behaviour might be in the way you implemented that client.sent(..). Do you always close and reopen the connection? Or what?

Related

I'm misunderstanding something on how to set up sockets, but I'm not suer if it's client side, server side, or both

I'm setting up a simple program to test starting a server, and I'm getting a silent failure state. My client seems to think it has sent, while my server doesn't think it's recieving. The two are managing the initial connection, it's just sending things after that where it's failing.
I've cut things down to the core of where it's currently failing I think.
Here's part of the Client code
public void Client (int port, String ip)
{
try {
sock = new Socket(ip, port);
System.out.println("Found the server.");
streamInput = new DataInputStream(sock.getInputStream());
// sends output to the socket
streamOutput = new DataOutputStream(
sock.getOutputStream());
streamOutput.writeChars("Client Begining Conversation");
System.out.println(streamInput.readUTF());
}
catch (UnknownHostException u) {
System.out.println(u);
return;
}
catch (IOException i) {
System.out.println(i);
return;
}
}
public static void main(String[] args) throws IOException {
// create the frame
try {
ClientGui main = new ClientGui();
main.Client(8000,"127.0.0.1");
main.show(true);
} catch (Exception e) {e.printStackTrace();}
Here's server code.
public Server(int port) throws Exception
{
ServerSocket gameServer = new ServerSocket(port);
Socket gameSocket = gameServer.accept();
System.out.println("Client has connected");
// to send data to the client
PrintStream dataOutput
= new PrintStream(gameSocket.getOutputStream());
// to read data coming from the client
BufferedReader reader = new BufferedReader( new InputStreamReader(
gameSocket.getInputStream()
));
//play logic
Play(reader,dataOutput);
public void Play(BufferedReader reader, PrintStream dataOutput) throws Exception
{
String received, textSent;
System.out.println("Waiting for response.");
received = reader.readLine();
System.out.println("Client has responded");
//contenue until 'Exit' is sent
while (received != "Exit" || received != "exit") {
System.out.println(received);
textSent = received + "recieved";
// send to client
dataOutput.println(textSent);
}
}
My client gets to here -
Found the server.
and my server gets to here -
Trying to start server.
Client has connected
Waiting for response.
At which point, it just hangs forever, each side waiting for the other. It doesn't throw an error, it just... waits until I force it closed.
So it appears that I'm either doing something wrong when I send with "streamOutput.writeChars" in my client, or I'm doing something wrong when I receive with my server with "reader.readLine();", but I can't figure out what.
Or I could be doing something more fundamentally wrong.
The problem is that reader.readLine() doesn’t return until it sees a new line character, but streamOutput.writeChars("Client Begining Conversation") doesn’t send one.
More generally, mixing a DataOutputStream on the client with a BufferedReader on the server won’t work reliably, as the latter expects plain text, while the former produces formatted binary data. For example, the character encoding might not match. The same applies to communication in the opposite direction with PrintStream and DataInputStream. It’s best to pick either a text based or binary protocol and then be consistent about the pair of classes used on both the client and server.
In the case of a text protocol, an explicit character encoding should be defined, as the default can vary between platforms. As a learning exercise, it might not matter, but it’s a good practice to be explicit about specifying a character encoding whenever handling networked communication. UTF-8 is a good choice unless there’s a specific reason to use another one.
In addition, it is generally preferred to use PrintWriter instead of PrintStream for text output in new code. Read this answer for an explanation.

Android socket doesn't write to output

I developed an application which communicates with server over TCP socket connection. When I tested it on emulator, it worked just fine. I could see all intended data flowing through. But when I run the application on my real device, it connects but not writes. To see what's happening, at server side I printed accepted clients and every received bytes. So it says "new client accepted" but never writes any received bytes which means no data received.
My code on Android application, runs without any exception:
clientSocket = new Socket(host, port);
PrintStream output = new PrintStream(clientSocket.getOutputStream());
clientSocket.getOutputStream().write(new byte[]{67,68,75}); //just some random stuff
clientSocket.getOutputStream().flush(); //neither this ...
output.print("hello"); //... nor this works
At the server side:
...
Socket clientSocket = server.accept();
DataStreamInput input = new DataInputStream(clientSocket.getInputStream());
System.out.println("New client accepted");
...
StringBuilder sb = new StringBuilder();
char ch = (char)input.readByte();
while (ch != '\0') {
System.out.println("BYTE received: "+ch); //should print sth no matter what, but doesn't
sb.append(ch);
ch = (char)client.getInput().readByte();
}
String data = sb.toString().trim();
dataReceived(data);
I don't understand why it works with the emulator but not with my device. (Samsung GT-I9500 btw) What could be the problem behind not sending or being unable to send the bytes? Any idea or any kind of help is appreciated. Thanks...
Edit: Something interesting happened. When I print something to output later in a different thread, it sends all of them with previous data.

Java communication with TCP socket and PIC stuck in read()

I try to communicate with a java application to a µController in wifi (Flyport).
I have a problem with the java application :
It first create a socket to communicate with the Flyport server, then send a message and receive the Flyport answer.
Everything work fine until the read part. I'm polling the read() function of the BufferedReader until it return -1, but it doesn't. The first read works fine, all the answer are red, but the application stay stuck when it tries to read again.
My code is very simple :
Java application :
try (
Socket clientSocket = new Socket(hostName, portNumber);
PrintWriter out =
new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in =
new BufferedReader(
new InputStreamReader(clientSocket.getInputStream()));
)
{
...//Connection and sending message works fine
}
char[] buffer = new char[500];
while ((in.read(buffer)) != -1) { // first read() works fine, second read() stay stuck...
System.out.println(buffer); // display all answer sent by flyport
}
The code in the flyport :
while(isClientConnected){
//check if client is still connected
...
//read client message
while((RxLen=TCPRxLen(sock))>0)
{
TCPRead(sock,bff,RxLen);
strcat(msg,bff);
}
//write back to the client that the order is received
TCPWrite(sock, msg, strlen(msg));
//process the client order
...
//Write to the client that the process is done
TCPWrite(sock, msg2, strlen(msg2));
}
The java application read msg and msg2 with the first read(). msg and msg2 have "\r\n" at the end.
Doesn't somebody can tell me where I am wrong ?
Is there a function from BufferedReading that tells how much data there is left to read ?
Thanks and regards.
NB : I try with a small buffer in the java application, the problem is the same, read() is stuck when there is nothing left to read...
You're reading from the socket until end of stream, and you're never causing end of stream, as you are never closing the socket at the sender. Either close the socket or don't read until end of stream.

How do I read a server reply without it blocking me?

I'm writing a proxy and have the following code:
Socket conUser;
Socket conDest;
try{
ServerSocket ss = new ServerSocket(Integer.parseInt(p.getProperty("proxy.port")));
while(true){
//Connect to user
conUser = ss.accept();
BufferedReader inputFromUser = new BufferedReader(new InputStreamReader(conUser.getInputStream()));
BufferedWriter outputToUser = new BufferedWriter(new OutputStreamWriter(conUser.getOutputStream(), "UTF8"));
//Get user request
StringBuffer req = new StringBuffer();
getUserRequest(inputFromUser, req);
System.out.println("User requested the following:");
System.out.println(req);
//Connect to server
InetAddress a = InetAddress.getByName(determineHost(req));
conDest = new Socket(a,80);
//Send request to server
BufferedWriter outputToServer = new BufferedWriter(new OutputStreamWriter(conDest.getOutputStream(), "UTF8"));
InputStreamReader inputFromServer = new InputStreamReader(conDest.getInputStream(), "UTF8");
outputToServer.write(req.toString());
outputToServer.flush();
System.out.println("==============================");
System.out.println("Server replied with the following:");
//Read reply from the server
//=========================================
int chars;
while ((chars = inputFromServer.read()) != -1) {
System.out.print((char)chars);
outputToUser.write(chars);
outputToUser.flush();
//serverReply.append(chars);
}
//Relay reply to user
//outputToUser.write(serverReply.toString());
//System.out.println(serverReply);
//outputToUser.flush();
conUser.close();
conDest.close();
}
}
catch (Exception e) {
System.err.println(e);
}
What happens is: I make a connection and it succeeds. I also send the request, and that succeeds too. I also get a reply, and am able to load the entire page's HTML, except that the read doesn't seem to terminate when it reaches the end of the content.
Specifically, I was attempting to load Google's homepage and the chunked transfer reached 0 (that is- end of chanked transfer), and thus there should've been no more input to read, but this did not cause the loop to stop reading. What's also strange to me is that pretty much all code examples of proxies do use this loop, and assuming they work, I don't see much differences between their code and mine.
How do I make the loop terminate correctly?
EDIT: for the record, yes- I know that the TCP connection should be kept open to handle further connections. This is not relevant to the problem I'm having. I need to get this loop to terminate per response.
In general the connection is not closed at the end of each response. Creating TCP connections is relatively time-consuming so the connection is left open, ready for you to send your next request.
Here are a couple of explanatory links:
http://en.wikipedia.org/wiki/HTTP_persistent_connection
http://en.wikipedia.org/wiki/HTTP_pipelining
If you want to terminate connection correctly after receiving HTTP response, your simple loop is not enough. You have to determine the end of message as described in section 4.4 Message Length of RFC 2616 and then close the connection.
However, it would be better to use existing libraries, such as built-in URLConnection.

TCP socket communication

I am creating a Chat in java.
I have a method (onMouseRelease) inside an object that creates a tcp server and waits for a socket like this:
ServerSocket server = new ServerSocket(port);
Socket channel = server.accept();
Now I want to make a thread that will loop and read data from the socket, so that once the user on the other side sends me a string, I will extract the data from the socket (or is it called packet? Sorry, I am new to this) and update a textbox to add the additional string from the socket (or packet?).
I have no idea how to READ (extract) the information from the socket(/packet) and then update it into a JTextArea which is called userOutput. And how to send a string to the other client, so that it will also could read the new data and update its JTextArea.
From what I know, for a 2 sided TCP communication you need one computer to host a server
and the other to connect (as a client) and once the connection is set the client can also receive new information from the socket. Is that true? and please tell me how.
Any help is appreciated! I know this is a bit long but I have searched a lot and didn't understand it (I saw something like PrintWriter but failed to understand).
You would have to do something like this;
InputStream in = new BufferedInputStream(channel.getInputStream());
You can then read characters from the socket using a loop;
char ch;
while (!finished) {
ch = in.read(); //read from socket
if(ch = -1) {
//nothing left to read
finished = true;
}
else {
//do something with ch
}
}
I can continue if you'd like?
Say we saved the incoming chars to a String called input, to update your text area you would call;
textArea.setText(input);
And to send text back to the client you would use a similar method to receiving, using an outputstream;
OutputStream out = new BufferedOutputStream(clientSock.getOutputStream());
out.write(output);

Categories

Resources