Java network server/client, cant find where is the failure - java

Hello I've reduced the code to this simple one:
Code from Server
byte[] data=new byte[1024];
try {
providerSocket=new ServerSocket(port);
while(true) {
connection=providerSocket.accept();
in=connection.getInputStream();
StringBuffer sb=new StringBuffer();
while((len=in.available())>0) {
in.read(data,0,len);
sb.append(new String(data,0,len));
reset(data); //writes -1 value to all bytes...
len=0;
}
System.out.println("Get "+sb.toString());
//does the same if I close() in, connection or do not close anything
}
}
catch(IOException ioException){ }
The client does somethig like:
Socket socket = new Socket(ip, port);
OutputStream out = socket.getOutputStream();
String s="Sample text";
out.write(s.getBytes());
out.flush();
out.close();
socket.close();
//closes cliente program
When I run Server and then I run client output is "Get Sample text", if I run again client output is "Get " whitout anything more, sure the error is very simple but I've tried everything I'm not viewing where it fails!!!
Why am I receiving ok the first transmission but not the next transmissions sent?
Sure my sample code has failures like not closing inputstream etc, but it does not change result if after the System.out.println() I write in.close() and/or connection.close()
Regards.

Don't use in.available(), the method doesn't do what you think it does. Instead, move the read() call to the while-loop condition.
int bytesRead = 0;
while((bytesRead = in.read(data)) != -1)
...

just comment out
\\ out.flush();
\\ out.close();
for a while and check,becuase i was also getting this error previously ,however this is the correct way but sometimes it creates problems.

Related

client socket issues when reading

I am having a real problem trying to find a solution to my problem and hope you guys could help. I have seen many socket examples online but have been unable to modify them for my use. Tbh, im struggling to even get an understanding of sockets. What I have been able to modify so far is below.
My problem, I believe is that my client program is not reading the incoming message from the server, could someone use my example to demonstrate where I am going wrong. Something in my mind tells me that my client socket closes before having a chance to read any incoming message. perhaps getting the client to wait until a message is recieved? If waiting is what is needed, how is this achieved? Thanks in advance.
CLIENT:
try {
Socket socket = new Socket("localhost", 55555);
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
out.write(score);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String rank = in.readLine();
System.out.println(rank);
in.close();
out.close();
socket.close();
}
catch(Exception e) {
System.out.print("Whoops! It didn't work!\n");
}
SERVER:
try {
System.out.println("Waitng for client to connect.....");
ServerSocket server = new ServerSocket(55555);
Socket socket = server.accept();
System.out.print("Client has connected!\n");
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String score = (in.readLine());
scor = Long.parseLong(score);
leaderboard(); ///// A METHOD THAT USES LONG SCORE TO CALCULATE RANKING- RETURNS A STRING VALUE CALLED RANK
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
System.out.print("Sending rank: " + rank);
out.write(rank);
out.close();
socket.close();
server.close();
}
catch(Exception e) {
System.out.print("Whoops! It didn't work!\n")`enter code here`;
}
Your code looks fine...
On your client program you're writing a line using:
out.write(score);
could you change this to:
out.println(score);
Also do the same on your server's program to take care of the reply:
out.println(rank);
Let me know how you go..
also if this helped, don't forget to upvote/mark this as a solution ;)
cheers
(Btw,as to what caused the problem:: in.read'LINE'() waits for the end of a line or newline(\n) for the string value to be saved. if you use out.write() then you have to and a newline character(\n) manually for the string to be read completely. if you use out.printline, then \n is added automatically to every string sent.
The readline method in your program was waiting for a newline character, which is why your program was stuck in that spot)

Proper way of closing Streams in Java Sockets

I saw some posts about this but I still can't find an answer.
This is how my server interacts with the client:
public void run () {
try {
//Read client request
InputStream is = server.getInputStream();
byte[] buff = new byte[1024];
int i;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
while ((i = is.read(buff, 0, buff.length)) != -1) {
bos.write(buff, 0, i);
System.out.println(i + " bytes readed ("+bos.size()+")");
}
is.close();
is = null;
//Do something with client request
//write response
OutputStream os = server.getOutputStream();
os.write("server response".getBytes());
os.flush();
os.close();
os = null;
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
And this is the client side:
public void run() {
try {
InetAddress serverAddr = null;
serverAddr = InetAddress.getByName("10.0.2.2");
socket = new Socket(serverAddr, 5000);
//Send Request to the server
OutputStream os = socket.getOutputStream();
os.write(jsonRequest.toString().getBytes("UTF-8"));
os.flush();
os.close();
os = null;
//Read Server Response
InputStream is = socket.getInputStream();
byte[] buff = new byte[1024];
int i;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
while ((i = is.read(buff, 0, buff.length)) != -1) {
bos.write(buff, 0, i);
System.out.println(i + " bytes readed ("+bos.size()+")");
}
is.close();
is = null;
//Do something with server response
} catch (UnknownHostException uhe) {
sendCallbackError(uhe);
} catch (IOException ioe) {
sendCallbackError(ioe);
}
}
As you can see, the client connects and send a request. Server read that request then writes a response that the client will read.
The problem with this code is the OutputStream.close() in the client and InputStream.close() in the server. As stated in the Javadocs, closing the stream will close the Socket. The result is that when the client tries to read the server response, the Socket is already closed.
I've managed to overcome this by calling Socket.shutdownInput and Socket.shutdownOutput instead. However I am still thinking whether this is the proper way of doing it
As a note, closing the streams with close() when server writes the response or when the client reads it doesn't create problems (I would guess the closing is synchronized between client and server).
So my questions are:
Is using the Socket shutdown methods a proper way?
Can I keep closing the last streams with close() (when sending and reading
response from server)
Could it happen that closing with shutdown would keep some data in
the buffer and wouldn't be sent?
You can do the following:
try{
}catch(){
}finally{
if(is!=null){
is.close();
}
if(os!=null){
os.close();
}
}
The problem with this code is the OutputStream.close() in the client and InputStream.close() in the server. As stated in the Javadocs, closing the stream will close the Socket.
Correct but the InputStream in the server isn't connected directly to a Socket: it is connected to something you don't know anything about. You can close it with impunity, although again you don't need to close it at all. You can close the OutputStream in the server if you like: although, again, as it isn't connected directly to a Socket, it may or may not have any effect other than flushing.
To address your actual question, you don't need to close the output stream in the client, but you do need to send an appropriate Content-Length: header. That way the server knows how much to read from the client. If this is only a GET request the content-length may well be zero. You don't need to call shutdownOutput(), although I guess there is nothing to stop you, and calling shutdownInput() doesn't do anything to the network anyway so again there is no point to it.

Java Networking: Explain InputStream and OutputStream in Socket

I have created a server by using ServerSocket. After that, I have created Client using Socket, and connect to this server.
After that, I do "some stuff" with InputStream and OutputStream is taken from Socket Object. But, I don't really understand inputStream and outputStream so much. Here is my simple code :
private Socket sock = null;
private InputStream sockInput = null;
private OutputStream sockOutput = null;
...
String msg = "Hello World";
byte[] buffer = null;
try {
sockOutput.write(msg.getBytes(), 0, test.length());
sockOutput.write("Hello StackOverFlow".getBytes(), 0, test.length());
buffer = new byte[test.length()];
sockInput.read(buffer, 0, test.length());
System.out.println(new String(buffer));
sockInput.read(buffer, 0, test.length());
System.out.println(new String(buffer));
} catch (IOException e1) {
e1.printStackTrace();
}
The result will be : "Hello World" and "Hello StackOverFlow".
Here is server side code :
private int serverPort = 0;
private ServerSocket serverSock = null;
public VerySimpleServer(int serverPort) {
this.serverPort = serverPort;
try {
serverSock = new ServerSocket(this.serverPort);
}
catch (IOException e){
e.printStackTrace(System.err);
}
}
// All this method does is wait for some bytes from the
// connection, read them, then write them back again, until the
// socket is closed from the other side.
public void handleConnection(InputStream sockInput, OutputStream sockOutput) {
while(true) {
byte[] buf=new byte[1024];
int bytes_read = 0;
try {
// This call to read() will wait forever, until the
// program on the other side either sends some data,
// or closes the socket.
bytes_read = sockInput.read(buf, 0, buf.length);
// If the socket is closed, sockInput.read() will return -1.
if(bytes_read < 0) {
System.err.println("Server: Tried to read from socket, read() returned < 0, Closing socket.");
return;
}
System.err.println("Server: Received "+bytes_read
+" bytes, sending them back to client, data="
+(new String(buf, 0, bytes_read)));
sockOutput.write(buf, 0, bytes_read);
// This call to flush() is optional - we're saying go
// ahead and send the data now instead of buffering
// it.
sockOutput.flush();
}
catch (Exception e){
System.err.println("Exception reading from/writing to socket, e="+e);
e.printStackTrace(System.err);
return;
}
}
}
public void waitForConnections() {
Socket sock = null;
InputStream sockInput = null;
OutputStream sockOutput = null;
while (true) {
try {
// This method call, accept(), blocks and waits
// (forever if necessary) until some other program
// opens a socket connection to our server. When some
// other program opens a connection to our server,
// accept() creates a new socket to represent that
// connection and returns.
sock = serverSock.accept();
System.err.println("Server : Have accepted new socket.");
// From this point on, no new socket connections can
// be made to our server until we call accept() again.
sockInput = sock.getInputStream();
sockOutput = sock.getOutputStream();
}
catch (IOException e){
e.printStackTrace(System.err);
}
// Do something with the socket - read bytes from the
// socket and write them back to the socket until the
// other side closes the connection.
handleConnection(sockInput, sockOutput);
// Now we close the socket.
try {
System.err.println("Closing socket.");
sock.close();
}
catch (Exception e){
System.err.println("Exception while closing socket.");
e.printStackTrace(System.err);
}
System.err.println("Finished with socket, waiting for next connection.");
}
}
public static void main(String argv[]) {
int port = 54321;
VerySimpleServer server = new VerySimpleServer(port);
server.waitForConnections();
}
My question is :
When I use sockOutput.write and I can get back those message back by sockInput.read. So, those message has been saved, right? If this true, does it saved on Server I have created or just saved in some other thing such as Socket Object.
If I have written to socket String A1, A2,... An so I will receive A1, A2, ... An String respectively, right?
A socket is an abstraction that you use to talk to something across the network. See diagram below...
In Java, to send data via the socket, you get an OutputStream (1) from it, and write to the OutputStream (you output some data).
To read data from the socket, you get its InputStream, and read input from this second stream.
You can think of the streams as a pair of one-way pipes connected to a socket on the wall. What happens on the other side of the wall is not your problem!
In your case, the server has another socket (the other end of the connection) and another pair of streams. It uses its InputStream (2) to read from the network, and its OutputStream (3) to write the same data back across the network to your client, which reads it again via its InputStream (4) completing the round trip.
Client Server
1. OutputStream -->\ /--> 2. InputStream -->
Socket <--> network <--> ServerSocket |
4. InputStream <--/ \<--3. OutputStream <--
Updated: in reply to comment:
Note that the streams and sockets just send raw bytes; they have no notion of a "message" at this level of abstraction. So if you send X bytes and another X bytes, then read X bytes and read another X bytes, then your system behaves as if there are two messages, because that's how you've divided up the bytes.
If you send X bytes, and another X bytes, then read a reply of length 2X, then you might be able to read a single combined "message", but as you've noticed, the underlying implementation of the streams can choose when to deliver chunks of bytes, so it might return X bytes, then X bytes, later, or 2X at once, or 0.5X four times...
InputStream and OutputStream are two completely separate streams. What you write into one has no a priori relation to what you read from the other. The InputStream gives you whatever data the server decides to send to you. I would also like to comment on this piece of your code:
sockOutput.write(msg.getBytes(), 0, test.length());
sockOutput.write("Hello StackOverFlow".getBytes(), 0, test.length());
You use the length of a string test (not shown in your code), which has nothing to do with the byte array you are passing as the first argument. This can cause an ArrayIndexOutOfBoundsException or truncation of your intended message.
Additional comments to your updated question
Reviewing your server-side code, it is not quite correctly written. You need to have try { handleConnection(...); } finally { socket.close(); } to ensure proper cleanup after an error, as well as when completing normally. Your code never closes anything on the server side.
Finally, and most critically, your entire code is written in a way that can result in a deadlock. Normally you need a separate thread to read and to write; otherwise the following may happen:
You attempt to write some data to the output;
The server reads it and tries to respond with data in your input;
But, since the buffers are too small, you don't manage to send everything because the server wants to first send something to you, then receive the rest; but you don't get to the receiving part before you have sent everything you've got.

C++ Client and Java Server

I did a Java Socket server, and a C++ Client.
However, the client connects to the server, without problems.
But when I write something client-server, the server doesn't catch the message.
What I'm doing wrong?
A little bit of the code of the Java Server:
DataInputStream dis=new DataInputStream(usrSocket.getInputStream());
ByteArrayOutputStream out = new ByteArrayOutputStream();
int data;
while((data = dis.read())>=0) {
out.write(data);
}
byte[] bytes = out.toByteArray();
String decrypt = new String(bytes);
if(decrypt.equals("status")){
System.out.println("Status emitted.");
}
System.out.println("Received a message.");
C++ Client writing:
QByteArray qba;
qba.append(text);
sock->write(qba.data());
qDebug() << "Send status";
I need help with that, thank you very much.
(that variable "text" it's a QString)
EDIT
Java server: That's only one part of all the code, the main thread waits for connections (Socket sock = server.accept()) and create a new thread for each user.
The code that I published of the java server, its one part of that threads for the users.
If you need ALL the code, plese tell me.
I will be waiting the answers!
Thank u very much!
Sorry if I answer ya late.
Try this code for Java Server.
ServerSocket ss = new ServerSocket(Port_No);
Socket incomingClient = ss.accept();
InputStream i = incomingClient.getInputStream();
OutputStream o = incomingClient.getOutputStream(); // Use it write to the Client Socket
InputStreamReader isr = new InputStreamReader(i);
BufferedReader br = new BufferedReader(isr);
String str = new String();
while ((str = br.readLine())!=null){
// do what you want with the data received in str.
}
As youre using QTcpSocket, it highly likely that you are running the client in the default asynchronous mode. This means after when you write after calling connectToHost, nothing will be sent as the socket is not connected.
Try using:
socket->connectToHost(hostAddress, hostPort, QIODevice::ReadWrite);
if (socket->waitForConnected()) {
QString text = "test string";
QByteArray array;
array.append(string);
qDebug() << socket->write(array);
} else {
// connect error!
}
Your Java code reads the socket until EOS and then prints something, which by the way is not a decryption operation. Your C++ client writes something and never closes the socket. So the server can never get out of the read loop.
If I read it correctly it is caused by the fact that your client is still running. Read() returns number >= 0 until the client socket is closed.

Java client socket using writeBytes

I'm reading a string from a buffer and writing it to a server. The problem I'm having is that the string never gets received by the server when I leave the socket open and write in a loop.
When I use this:
try {
Socket send = new Socket("localhost", 1490);
DataOutputStream out = new DataOutputStream(send.getOutputStream());
String message = null;
while ((message = buffer.get()) != null){
out.writeBytes(message);
}
out.close();
send.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
the server doesn't receive the string, but when I do this it works properly:
try {
String message = null;
while ((message = buffer.get()) != null){
Socket send = new Socket("localhost", 1490);
DataOutputStream out = new DataOutputStream(send.getOutputStream());
out.writeBytes(message);
out.close();
send.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
Obviously I don't want to keep opening and closing the socket, though. What is the problem?
You need to flush your socket every time you want to send a data packet.
Closing a socket forces an automatic flush and that explains why your data is getting sent on socket close.
The data is not being written to the socket even when you close it? (in your first snippet that is)
Also, have you tried to use the flush method? You can read about it here: http://docs.oracle.com/javase/1.4.2/docs/api/java/io/DataOutputStream.html#flush() and your code will look like:
try {
Socket send = new Socket("localhost", 1490);
DataOutputStream out = new DataOutputStream(send.getOutputStream());
String message = null;
while ((message = buffer.get()) != null){
out.writeBytes(message);
out.flush();
}
out.close();
send.close();
} catch (IOException ex) {
ex.printStackTrace();
}
Let me make a guess.
Does the buffer.get() method block? If so, then the problem is that out.writeBytes(message) does not guarantee that the entire byte representation to be pushed to the server. Instead. there is a good chance that your client has buffered bytes waiting to be flushed through to the server.
If this is what is going on, then calling flush after each call to writeBytes will fix the problem.
But if the buffer.get() method doesn't block, then calling flush won't make any difference. In fact, it will just increase the network traffic. So adding the flush "just in case" is a bad idea.
Another possibility is that there is something wrong with the server-side code.

Categories