I have the following problem, I have a simple TCP class in my application that sends a message off to a device for a query, the device then responds with the message however there is no end of line character of any description because it is coming from a serial converter, after initially atempting to use the readline function and discovering it requires the eol character before outputting I have tried the scanner function which works fine unless the device doesnt reply to that request for some reason, my application then freezes, is it possible to set a timeout on the scanner function so that it then drops the connection and moves on or is there a better way to do this? my code is below:
public String Send_TCP ( InetAddress IPAddress, int POrt, String InData) throws IOException
{
Socket socket = null;
PrintWriter out = null;
BufferedReader in = null;
try {
socket = new Socket(IPAddress, POrt);
out = new PrintWriter(socket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
} catch (UnknownHostException e) {
System.err.println("Don't know about host");
System.exit(1);
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection");
System.exit(1);
}
BufferedReader read = new BufferedReader(new InputStreamReader(System.in));
;
System.out.print("Connected, Sending:"+ InData);
out.println(InData);
System.out.println("Equals");
String str1 = new Scanner(in).useDelimiter(">").next() + ">";
System.out.println(str1);
System.out.println("Equals");
out.close();
in.close();
read.close();
socket.close();
return str1;
}
}
I'm not sure that I understand your question correctly but you can set a timeout on the socket: socket.setSoTimeout(int timeout).
See: javadoc
I believe the following achieves what I need it to, basically checking if the buffer exists, if it doesnt then it waits and checks again avoiding the trap of the scanner function if the message never arrives if it does it reads it.
try {
BufferedReader rd = new BufferedReader(new InputStreamReader(sock.getInputStream()));
int count = 1;
do {
if (rd.ready()){
System.out.println ("Response Ready");
str = new Scanner(rd).useDelimiter(">").next()+">";
count = 501;
}
Thread.sleep(10);
System.out.println ("Response Not Ready" + count);
count ++;
} while (count < 25);
Related
Having read tens of examples online, I am still stuck with the problem.
I am sending a message from my client in Java to a server in C++. After receiving the hand-shake message, the server sends back the following data:
"0000:1111:2222:3333:4444
END_CONNECT_DATA"
As soon as the last line (terminator) is read by the client, it should close the connection.
This is how I do it:
Socket socket = null;
String terminator = "END_CONNECT_DATA";
try
{
int serverPort = 7767;
String ip = "192.168.1.10";
String messageOut = "HAND-SHAKE MESSAGE";
socket = new Socket(ip, serverPort);
DataInputStream input = new DataInputStream( socket.getInputStream());
DataOutputStream output = new DataOutputStream( socket.getOutputStream());
//Send message
output.writeBytes(messageOut);
//Read Response
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
StringBuffer sb = new StringBuffer();
String s = "";
while((s = br.readLine()) != null)
{
System.out.println("CHECK !!!");
System.out.println(s);
sb.append(s);
if(s.contains(terminator))
{
System.out.println("CHECK TERMINATOR");
break;
}
}
socket.close();
String data = sb.toString();
System.out.println("FULL DATA:\n");
System.out.println(data);
}
catch (UnknownHostException e)
{
System.out.println("Sock:"+e.getMessage());
}
catch (EOFException e)
{
System.out.println("EOF:"+e.getMessage());
}
catch (IOException e)
{
System.out.println("IO:"+e.getMessage());
}
finally
{
if(socket!=null)
{
try
{
socket.close();
}
catch (IOException e)
{
}
}
}
}
What I get back from the server is only the first line. The cursor goes to the next line and continues blinking. The socket connection is not closed. Looks like the client is not reading the terminator (the second line of the message) at all.
Any ideas?
Thanks a lot!
As documented, the loop fails to read in the second line as it's not terminated with \r or \n. Therefore, returning only the result up till then, which is the first line as described.
You'll need to either add in a \r or \n right after the terminator or use BufferedReader.read() instead and check manually or adopt another strategy to read in the message
Clearly the peer is neither sending a line terminator after the last line nor closing the socket. Ergo using readLine() to read those messages is not correct. If you can adjust the peer, do so.
I wrote a Java socket server which will keep connection alive until client disconnected. And my client code will keep pushing message to this server app.
But when I run those programs a while, I also seem an unusual condition that Server will hangs while reading input stream from client within unpredictable period. It always hang at inData.read(b) because I see it printed "receiving..." on log when this problem occurred"; even I killed my client, server app still hangs right there.
But when I press Ctrl+C at the console which runs server app after this problem occurred, it will continue to work. This is really annoying.
Is there anyway to solve this Unusual problem nicely?
Server Code:
static ServerSocket server;
try {
server = new ServerSocket("1234");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Socket socket = null;
String inIp = null;
BufferedInputStream inData;
BufferedOutputStream outData;
while (true) {
try {
synchronized (server) {
socket = server.accept();
}
inIp = String.valueOf(socket.getInetAddress());
if (Log4j.log.isEnabledFor(Level.INFO)) {
Log4j.log.info("Incoming connection " + inIp);
}
while (true) {
inData = new BufferedInputStream(socket.getInputStream());
outData = new BufferedOutputStream(socket.getOutputStream());
String reply = "Hey";
byte[] b = new byte[10240];
String data = "";
int length;
if (Log4j.log.isEnabledFor(Level.INFO)) {
Log4j.log.info("InetAddr = " + inIp + ", receiving...");
}
// read input stream
length = inData.read(b);
data += new String(b, 0, length);
if (Log4j.log.isEnabledFor(Level.INFO)) {
Log4j.log.info("Data Length: " + length + ", Received data: " + data);
}
// output result
outData.write(reply.getBytes());
outData.flush();
}
} catch (Exception e) {
String tempStr = e.toString();
Log4j.log.error("Service error during executing: " + tempStr);
}
}
Client Code:
Socket client = new Socket();
InetSocketAddress isa = new InetSocketAddress("127.0.0.1", "1234");
String data = "Hi";
while(true) {
try {
if(!client.isConnected())
client.connect(isa, 30000);
BufferedOutputStream out = new BufferedOutputStream(client.getOutputStream());
BufferedInputStream in = new BufferedInputStream(client.getInputStream());
// send msg
out.write(data.getBytes());
out.flush();
System.out.println("Message sent, receiving return message...");
// get return msg
int length;
byte[] b = new byte[10240];
// read input stream
length = in.read(b);
retMsg = new String(b, 0, length);
System.out.println("Return Msg: " + retMsg);
Thread.sleep(60000);
} catch (java.io.IOException | InterruptedException e) {
System.out.println("Socket Error!");
System.out.println("IOException :" + e.toString());
}
}
try {
server = new ServerSocket("1234");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Don't write code like this. The catch block should be at the end, and all the code that depends on the success of new ServerSocket should be inside the try block.
synchronized (server) {
socket = server.accept();
}
Synchronization is not necessary here.
while (true) {
inData = new BufferedInputStream(socket.getInputStream());
outData = new BufferedOutputStream(socket.getOutputStream());
A large part of the problem, if not all of it, is here. You keep creating new buffered streams, every time around this loop, which means that anything the previous streams have buffered is thrown away. So you are losing input. You should create both these streams before the loop.
while(true) {
try {
if(!client.isConnected())
client.connect(isa, 30000);
This is pointless. Remove. You haven't shown how the client socket was created, but if you created it unconnected you should have connected it before entering this loop.
BufferedOutputStream out = new BufferedOutputStream(client.getOutputStream());
BufferedInputStream in = new BufferedInputStream(client.getInputStream());
Here again you must create these streams ahead of the loop.
I am trying to create an application that will count the amount of times a button has been clicked. This client would connect to a server, and when the user clicks the button, it should increment the counter on the server. The server should then send back the current amount of clicks to the client. But that's where I'm having a bit of problems.
This is the relevant client-sided code.
public void actionPerformed(ActionEvent arg0) {
try {
OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
String target = "";
bw.write("increment" + "\n");
bw.flush();
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String id = br.readLine();
System.out.println("test: " + id);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
The client stops at:
String id = br.readLine();
I just want to get the output from the server.
This is the relevant server-sided code.
public void run() {
try {
while (true) {
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is); //Create the input Streams
BufferedReader br = new BufferedReader(isr);
String input = br.readLine();
System.out.println("got input");
OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
System.out.println("wrote to out");
if(input.equals("increment" + "\n")) {
totalBets++;
System.out.println("inif");
bw.write(totalBets);
System.out.println("wrote");
bw.flush();
System.out.println("flushed");
System.out.println("Total Bets: " + totalBets);
}
}
} catch (IOException e) {
log("Error handling client# " + clientNumber + ": " + e);
} finally {
try {
socket.close();
} catch (IOException e) {
log("Couldn't close a socket, what's going on?");
}
log("Connection with client# " + clientNumber + " closed");
}
}
I found that it also stops here:
String input = br.readLine();
I'm just trying to get the bw.write("imcrement") from the client, so the server can increment the counter, and send back the total clicks.
Any help?
Thank you.
You are writing the totalBets value using BufferedWriter.write(int).
This interprets the value as a single character. So, for example, if totalBets is 65, it writes the character 'A'!
Moreover, it does not add a newline. So the client reads that 'A' but tries to read more characters as it is trying to read a whole line. Remember that you have to write lines to read lines.
Thus, you should replace the part that writes totalBets with:
bw.write(String.valueOf(totalBets));
bw.newLine();
Also remember, as I pointed in a comment, that you have to write a line with a \n (or preferably BufferedWriter.newLine()), but when you read the line on the other side, the line separator is stripped away, so you should compare the string you expect without a \n.
You need to set TCP_NODELAY on the client's socket. The default is for data to be buffered until it will fill an entire packet. When the buffer is full, a packet is sent. However, for this protocol you want the data to be sent immediately so that the server can respond.
I frequently use wireshark when testing and debugging my networking code. It will show exactly what packets are sent and received. (note, however, that on Windows you can not capture from the loopback interface; this is a limitation of Windows and does not apply to other systems)
I'm writing a simple server in Java, and I'm able to retrieve incoming data from the client on the server side, but not on the client side due to a 2000ms timeout. Anyone know why this times out?
This is the server's code:
private static void listen() throws IOException {
while(true) {
Socket clientSocket = serverSocket.accept();
StringBuilder bufferedStringInput = new StringBuilder();
CharBuffer cbuf = CharBuffer.allocate(4096);
try {
InputStream is = clientSocket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF8"));
int noCharsLeft = 0;
while ((noCharsLeft = br.read(cbuf)) != -1) {
char[] arr = new char[noCharsLeft];
cbuf.rewind();
cbuf.get(arr);
bufferedStringInput.append(arr);
cbuf.clear();
}
System.out.println(bufferedStringInput.toString());
} catch (IOException e) {
System.out.println("Error received client data: " + e.getMessage());
}
String message = "Hello client";
try {
PrintWriter out = new PrintWriter(clientSocket.getOutputStream());
out.print(message);
} catch (IOException e) {
System.out.println("Error getting output stream from client: " + e.getMessage());
}
clientSocket.close();
}
}
You're reading the input until end of stream, which only happens when the peer closes the connection, then you're trying to write to it, so of course you get a broken pipe. Doesn't make sense. You should just read the input until you have one entire request, whatever that means in your protocol.
There are other problems lurking here:
If the client code uses readLine(), you're not sending a line terminator: use println(), not print(), and close the PrintWriter, not just the client socket.
cbuf.rewind()/get()/clear() should be cbuf.flip()/get()/compact().
But it would make more sense to read directly into a char[] cbuf = new char[8192]; array, then bufferedStringInput.append(cbuf, 0, noCharsLeft), and forget about the CharBuffer altogether. Too much data copying at present.
noCharsLeft is a poor name for that variable. It is a read count.
yes i did look at the tutorials on sun and they didn`t help in my case, only transferred the first command.
I`ve got a method
public void openConnection() throws IOException{
serverSocket = new ServerSocket(5346);
Socket simSocket = serverSocket.accept();
is = simSocket.getInputStream();
os = simSocket.getOutputStream();
writer = new PrintWriter(os);
isReader = new InputStreamReader(is);
reader = new BufferedReader(isReader);
System.out.println("Connection succesfull.");
}
and
public void sendTo(int command) {
try {
writer.println(command);
writer.flush();
} catch(Exception e) {
System.out.println("Error sending command to the robot");
System.out.println(e.toString());
}
}
in the sending side, and
public static void setUpConnection() {
try {
socket = new Socket(InetAddress.getLocalHost(), 5346);
is = new InputStreamReader(
socket.getInputStream());
reader = new BufferedReader(is);
writer = new PrintWriter(socket.getOutputStream());
System.out.println("Simulator: connection succesful");
} catch (IOException e) {
e.printStackTrace();
}
}
and
while (true) {
intCommand = reader.read();
ett = reader.readLine(); // does nothing, but without this line it doesn't work
command = (char) intCommand;
in the receiving side. It works perfectly sending a char or an ascii number of a char. What i need is to change this code to send integers or simply array of bytes instead of a char. if i simply leave just InputStream and OutputStream it does receive the first command and thats it, while these methods continuously receives what is sent through sendTo. Even in sockets documentation they only have exmample with sending chars only.
Just code your server to store the received value as an int instead of a char.