tags:

views:

904

answers:

4

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:

  1. 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.

  2. 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?

A: 

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 espects (protocol)... Maybe you should try something like

String message = "ABC\n";
Carlos Heuberger
from what i understand server should be reading whatever is coming to the pipe. It does not expect any carriage returns (as demonstrated when i send message the first time)
Rocket Surgeon
maybe you should give more details about the server. I tested your code using NC (netcat) as server: every time I type Y followed by ENTER at the console for your code, I get an additional "ABC" on the server end.
Carlos Heuberger
+1  A: 

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.

nos
What my question is: if we are flushing an array of bytes to a stream, they should at least "show up" on the other end. You care about delimiter at the point where your business logic starts processing them
Rocket Surgeon
You're right. But you do not show the server code that does the read. So it's hard to know if it does the right thing. e.g. does it call read only once ? Or does it loop till the stream is closed ?
nos
+1  A: 

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)

Carlos Heuberger
Tried using TCP Test Tool and getting same result. Looks like the problem is with server side, not with java stream or flushing. Trying to find out if I'm allowed to run Network Analyzer. Got Wireshark for those purposes.
Rocket Surgeon
A: 

Hello guys,

i am experiencing a similar problem so thought of posting it here to get help...

I have 2 peer processes communicating over tcp with each other. I am dealing with very large chunk of data (approx 100kB)..

P1 writes 100kB , but when the P2 tries to read the data it is able to read only partial data say 60kB or so.

I am programming in Java. I am using

BufferedInputStream in = new BufferedInputStream(client.getInputStream()); int c=0; byte[] b= new byte[5555555]; c=in.read(b);

To read the bytes written by P1... Is there a limitation on the amount of bytes that can be sent over tcp ?? Is it a problem ??

I doubt there is a limitation. Try creating BufferedInputStream specifying appropriate buffer size (using new BufferedInputStream(inputStream, bufferSize) constructor).
Rocket Surgeon