TCP socket communication - java

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);

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.

Unresponsive socket read buffer

I am trying to send data to one of my servers and receive an ACK back from it. However, the processing gets hung up when waiting for a response from the server. I know for a fact that there is a connection because I can see the data reaching the server. I also know that the server is outputting data correctly because my C# client is receiving data back from the server. I will note that this client is running on a centOS virtual machine. The server is a remote windows machine. I wouldn't imagine that there would be an issue due to the virtual environment because I am able to use an SNMP java client (SNMP4j package) to make calls to a remote server. I believe my server is outputting raw binary too, but I would expect to see some kind of output either way.
// A Java program for a Client
import java.net.*;
import java.io.*;
public class Client
{
// initialize socket and input output streams
private Socket socket = null;
private DataInputStream input = null;
private DataOutputStream out = null;
private DataInputStream serveroutput= null;
// constructor to put ip address and port
public Client(String address, int port)
{
// establish a connection
try
{
socket = new Socket(address, port);
System.out.println("Connected");
// takes input from terminal
input = new DataInputStream(System.in);
// sends output to the socket
out = new DataOutputStream(socket.getOutputStream());
serveroutput = new DataInputStream(socket.getInputStream());
}
catch(UnknownHostException u)
{
System.out.println(u);
}
catch(IOException i)
{
System.out.println(i);
}
// string to read message from input
String line = "";
// keep reading until "Over" is input
while (!line.equals("Over"))
{
try
{
line = input.readLine();
out.writeUTF(line);
System.out.println(serveroutput.readLine())
}
catch(IOException i)
{
System.out.println(i);
}
}
// close the connection
try
{
input.close();
out.close();
socket.close();
}
catch(IOException i)
{
System.out.println(i);
}
}
Could be great if you would share the otherside codes. (sorry cannot comment yet)
Try use something else over writeUTF(), simply maybe a PrintStream, as mentioned by #marquis-of-lorne (read|write)UTF may be confusing by the peer.
Also this might be a good practice to flush() out the output from both side when there is nothing else to send to make sure data is sent completely.
You may also try BufferedReader over InputDataStream as you are trying to read lines. readLine() from InputDataStream is deprecated.

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.

Java TCP server - android client packet loss

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?

Categories

Resources