I have a TCP-server client pair. The client has a thread for Handling the data which comes from the server. the problem is, before the first data is received from the server, the Buffered reader is blocked. But once the first data is received, it keeps sending 0's in between the usefull data. Does anyone have any idea why? And how to solve this?
connection = new Socket(ip, port);
output = new DataOutputStream(connection.getOutputStream());
input = new BufferedReader(new InputStreamReader(connection.getInputStream()));
And this part is modified to handle the 0's, yet this isn't ideal:
try {
opcode = (char) input.read();
} catch (IOException ex) {
ErrorFrame erfframe = new ErrorFrame("De verbinding is verbroken voordat we de opcode van het packet konden lezen", "Herverbinden", IRIGui.ConnectionType);
}
System.out.println("Data received!!" + opcode);
int opcodenr = Character.getNumericValue(opcode);
char sensortype = '0';
try {
do {
sensortype = (char) input.read();
} while (sensortype == 0);
} catch (IOException ex) {
ErrorFrame erfframe = new ErrorFrame("De verbinding is verbroken voordat we de sensortype van het packet konden lezen", "Herverbinden", IRIGui.ConnectionType);
}
The server code:
public static void main(String argv[]) throws Exception {
ServerSocket welcomeSocket = new ServerSocket(25566);
while (true) {
Socket connectionSocket = welcomeSocket.accept();
BufferedReader inFromClient =
new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());
int request = inFromClient.read();
System.out.println("erjioejfioe " + request);
if (request == 4) {
outToClient.writeBytes("41");
outToClient.write(5);
outToClient.writeInt(5);
outToClient.writeInt(3);
outToClient.writeInt(6);
outToClient.writeInt(5);
outToClient.writeInt(1);
}
request = 0;
request = inFromClient.read();
System.out.println("erjioejfioe " + request);
if (request == 4) {
System.out.println("SENDING THE SHIT");
outToClient.writeBytes("41");
outToClient.write(5);
outToClient.writeInt(3);
outToClient.writeInt(7);
outToClient.writeInt(2);
outToClient.writeInt(4);
outToClient.writeInt(3);
System.out.println("We get here!!");
}
break;
}
}
You are writing ints, which are 32 bits, and in your case all have three leading zero bytes, and reading chars, which are 16 bits, so every odd char you read consists of two zero bytes. This doesn't make any sense. If you write with writeInt(), read with readInt(). Same goes for all the other DataInput/OutputStream methods. Use them symmetrically.
There is no evidence here of anything not blocking.
Related
So the the server program consists of the following code:
import java.io. * ;
import java.net. * ;
import java.util. * ;
public class TimeServer {
public static void main(String[] args) {
try {
//Create sockets
ServerSocket ss = new ServerSocket(60000);
Socket rs = ss.accept();
//create streams
BufferedInputStream bs = new BufferedInputStream(rs.getInputStream());
InputStreamReader isr = new InputStreamReader(bs);
BufferedOutputStream bos = new BufferedOutputStream(rs.getOutputStream());
PrintWriter pw = new PrintWriter(bos);
//set timeout
rs.setSoTimeout(20000);
int c = 0;
StringBuilder sb = new StringBuilder();
//while loop reads in a character until a period (includes period)
while (((char) c != '.')) {
c = isr.read();
//append each char to a string builder
sb.append((char) c);
}
//convert stringbuilder to string
String str = sb.substring(0);
//If string equals "time." returns time else error message
if (str.compareTo("time.") == 0) {
Date now = new Date();
pw.print("time is: " + now.toString());
pw.flush();
}
else {
pw.print("Invalid syntax: connection closed");
pw.flush();
}
//close socket
rs.close();
//close serversocket
ss.close();
} catch(IOException i) {
System.out.println(i.getMessage());
}
}
}
The code for the client is:
import java.io. * ;
import java.net. * ;
import java.util. * ;
public class TimeClient {
public static void main(String[] args) {
try {
//create socket
Socket sock = new Socket("localhost", 60000);
//create streams
BufferedInputStream bis = new BufferedInputStream(sock.getInputStream());
InputStreamReader isr = new InputStreamReader(bis);
BufferedOutputStream bos = new BufferedOutputStream(sock.getOutputStream());
PrintWriter pw = new PrintWriter(bos);
//set timeout
sock.setSoTimeout(20000);
//write argument to stream, argument should be "time." to recieve time
pw.write(args[0]);
pw.flush();
int c = 0;
StringBuilder sb = new StringBuilder();
//while loop reads each character into stringbuilder
while ((c != -1)) {
c = isr.read();
sb.append((char) c);
}
//stringbuilder converted to string and printed
String str = sb.substring(0);
System.out.println(str);
//socket closed
sock.close();
} catch(IOException i) {
System.out.println(i.getMessage());
}
}
}
The problem is that if I run each program in a separate cmd.exe, they do not communicate despite using localhost as the IP address. I can't seem to find the logical error in the code which causes this and wondered if anyone could help?
The problem is that you are using a BufferedOutputStream and you close the socket immediately after writing on the PrintWriter. What you have written remains in the buffer and the socket is closed before anything has been sent to the client.
You need to flush before closing in order to force the content of the buffer to be sent:
...
//close socket
pw.flush();
rs.close();
...
TimeClient contains a minor error: you loop receiving until you get a -1 which is correct, but you append that -1 to the StringBuilder which is wrong. It should be:
//while loop reads each character into stringbuilder
while(true){
c = isr.read();
if (c == -1) { break; }
sb.append((char) c);
}
But this should never prevent the text to be displayed...
i'm working on an instant messaging project which it's client side is android and server is java
i need to use socket with streams
here is my protocol (something like HTTP) :
Method : attachment \n
Content-Length : {some-int-value} \n
\r\n
binary data bla bla bla...
lets assume i want to send this message from client to server
by doing so exchanging header section goes pretty well
but reading binary data at the server side never complete and server goes into hang for good
Client side code :
Socket socket = new Socket();
SocketAddress address = new InetSocketAddress(SERVER_ADDRESS, SERVER_PORT);
try {
socket.connect(address);
InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF-8"));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out, "UTF-8"));
byte[] data = getSomeBinaryData();
writer.write("Method : attachment" + "\n");
writer.write("Content-Length : " + data.length + "\n");
writer.write("\r\n");
writer.flush();
out.write(data); // write binary data
// do more exchange later
} catch (IOException ex) {
// handle exception
}
Server starter code :
public static void main(String[] args){
ExecutorService pool = Executors.newFixedThreadPool(50);
try (ServerSocket server = new ServerSocket(PORT_NUMBER)) {
while (true) {
try {
Socket connection = server.accept();
Callable<Void> task = new ClientTask(connection);
pool.submit(task);
} catch (IOException ex) {}
}
} catch (IOException ex) {
System.err.println("Couldn't start server");
}
}
Server Task thread for each client :
class ClientTask implements Callable<Void> {
private Socket connection;
private HashMap<String, String> header = new HashMap<>();
private byte[] content;
ClientTask(Socket c) {
this.connection = c;
}
#Override
public Void call() throws Exception {
InputStream in = connection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF-8"));
readHeader(reader);
System.out.println("incoming message : " + header.get("Method"));
int contentLength = Integer.parseInt(header.get("Content-Length"));
content = new byte[contentLength];
int bytesRead = in.read(content, 0, contentLength);
System.out.print(bytesRead);
return null;
}
private void readHeader(BufferedReader reader){
try {
char c;
StringBuilder builder = new StringBuilder();
while ((c = (char) reader.read()) != '\r'){
if(c == '\n'){
String line = builder.toString();
line = line.replaceAll(" ", "");
String[] sections = line.split(":");
header.put(sections[0], sections[1]);
builder = new StringBuilder(); // clear builder
}else {
builder.append(c);
}
}
reader.read(); // skip the last \n character after header
} catch (IOException e) {
e.printStackTrace();
}
}
As James said a clue I wanted to share the solution
maybe it help someone with similar issue
in the call method of ClientTask class i should use this code :
#Override
public Void call() throws Exception {
InputStream in = connection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF-8"));
readHeader(reader);
System.out.println("incoming message : " + header.get("Method"));
// read binary Content
int bytesRead = 0;
int bytesToRead = Integer.parseInt(header.get("Content-Length"));
content = new byte[bytesToRead];
while (bytesRead < bytesToRead) {
int result = in.read(content, bytesRead, bytesToRead - bytesRead);
if (result == -1)
break; // end of stream
bytesRead += result;
}
return null;
}
I need a bufferread to work with a client which closes when the word "CLOSE". THE client closes, I just can't get the sever to close once messages have been sent through it.
Heres what code I have:
`
import java.io.*;
import java.net.*;
class TCPClient2 {
public static void main(String argv[]) throws Exception {
String sentence;
String modifiedSentence;
BufferedReader inFromUser
= new BufferedReader(new InputStreamReader(System.in));
Socket clientSocket = new Socket("143.53.30.136", 49250);//port number and ip address of client
DataOutputStream outToServer
= new DataOutputStream(clientSocket.getOutputStream());
InputStream sin = clientSocket.getInputStream();
// Just converting them to different streams, so that string handling becomes easier.
DataInputStream inFromServer = new DataInputStream(sin);
try {
do {
System.out.print("Enter message : ");
sentence = inFromUser.readLine();
outToServer.writeBytes(sentence + '\n');
//Question B4
//if statement for closing the socket connection
if (sentence.equals("CLOSE")) {
clientSocket.close();
//closes client socket
System.out.println("Socket Closed");
//prints socket closed to tell user socket has closed
System.exit(0);
}
outToServer.writeBytes(sentence + '\n');
System.out.print("Message sent! please wait for server message: ");
modifiedSentence = inFromServer.readUTF();
System.out.println("FROM SERVER: " + modifiedSentence);
} while (!sentence.equals("CLOSE"));
} catch (IOException e) {
}
clientSocket.close();
}
}`
AND the server:
`
/*
chris and paul
*/
import java.io.*;
import java.net.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class TCPMultiThreadServer {
private static ServerSocket welcomeSocket;
//port number the server is using
private static final int PORT = 49250;
private static int clientNo =1;
public static void main(String argv[]) throws Exception
{
System.out.println("Opening port...\n");
try
{
// ServerSocket listens for new connections on specified port
welcomeSocket = new ServerSocket(PORT);
do
{
Socket client = welcomeSocket.accept();
System.out.println("\nNew client accepted.\n");
//Create a thread to handle communication with
//this client and pass the constructor for this
//thread a reference to the relevant socket...
TCPMultiThreadServer.ClientHandler handler =
new TCPMultiThreadServer().new ClientHandler(client,clientNo);
handler.start(); // Calls run() method in ClientHandler
clientNo++;
} while (true);
} catch (IOException e) {}
}
// Original work not credited
class ClientHandler extends Thread
{
private Socket client;
private BufferedReader inFromClient;
private BufferedReader text_to_Client;
private DataOutputStream outToClient;
private FileWriter Filestream;
private BufferedWriter out;
public int clientNo;
public boolean stopping;
//part A question 4, adding buffer string array to the program
private String[] buffer; //creation of buffer string array.
private int bufferI; // Index of the last thing inserted into the array
public ClientHandler(Socket socket, int clientNos)
{
//Set up reference to associated socket
client = socket;
clientNo= clientNos;
try
{
// Gets access to input/output stream of socket
inFromClient =
new BufferedReader(new InputStreamReader
(client.getInputStream()));
text_to_Client =
new BufferedReader(new InputStreamReader(System.in));
outToClient =
new DataOutputStream(client.getOutputStream());
} catch(IOException e) {}
}
public void run()
{
try
{
stopping = false;
//Question A4 buffer continued
buffer = new String[4];
//generates buffer string array containing 4 strings
bufferI = 0;
// make sure bufferIndex = 0
String clientSentence;
Thread mythread = Thread.currentThread();
do
{
//Accept message from client on socket's input stream
OutputStream sout = client.getOutputStream();
// Just converting them to different streams, so that string
// handling becomes easier.
DataOutputStream text_to_send = new DataOutputStream(sout);
clientSentence = inFromClient.readLine();
System.out.println("Message received from client number " +
clientNo + ": "+ clientSentence);
// String to be scanned to find the pattern.
String line = clientSentence;
String pattern = "[C][L][O][S][E]";
// Create a Pattern object
Pattern r = Pattern.compile(pattern);
// Now create matcher object.
Matcher m = r.matcher(line);
//if (m.find( )) {
// System.out.println("Found value: " + m.find() );
// System.out.println("Found value: " + m.group(1) );
//System.out.println("Found value: " + m.group(2) );
//} else {
// System.out.println("NO MATCH");
//}
//part B question 4 close command
//if statement for closing the socket connection if it is equal to close
if(m.matches())
{ //prints socket closed to tell user socket has closed
System.out.println("Socket connection to client number "
+ clientNo + " closed");
try
{
} catch(Exception e) {}
out.flush();
out.close(); // Close the file handler
client.close(); // Close the connection with the client,
clientNo--; // Decrement the number of clients
}
else
{
//part A question 4, adding buffer string array to the program
// looks to see if the buffer string array is full
//and also looks to see if bufferIndex is in range
if (bufferI > buffer.length-1)
{
// Print BUFFER FULL
System.out.println("BUFFER FULL");
// Clear clientSentence string
clientSentence = " ";
// For loop which travels through the buffer array of string
for (int i=0; i<buffer.length; i++)
{
// Append buffer element to clientSentence string
clientSentence += buffer[i] + " , ";
buffer[i] = null; // makes the buffer null
}
bufferI = 0; // Reset bufferI back to 0 so writing to the buffer can restarted
// prints buffer cleared back to the clients
text_to_send.writeUTF("BUFFER CLEARED :" +
clientSentence);
}
else
{
buffer[bufferI] = clientSentence;
System.out.println("Buffer " + bufferI+ ": " +
buffer[bufferI]);
bufferI++;
System.out.println("Enter Message: ");
// Reads message from server interface
// and sends it to the client
clientSentence = text_to_Client.readLine();
text_to_send.writeUTF(clientSentence);
System.out.println("Your message: " +
clientSentence);
}
}
if (mythread.activeCount() == 2 &&
(clientNo ==0 || clientNo >0) &&
clientSentence.equals("CLOSE"))
{
System.exit(0);
}
} while(!clientSentence.equals("CLOSE"));
client.close();
} catch(IOException e) {}
}
}
}
`
I have a task to do this.
Create a client and server socket interaction which accepts byte data and converts the byte data data received at server in the String and send back the response with the confirmation of the data conversation with success/unsuccess as the data passed will be with fix data length format so the validation should be done at server end.
As for e.g.
there are fields which ur sending to server like,
field 1 - number
field 2 - String
field 3 as Floating number i.e. 108.50
After conversion from byte to String :
152|any msg|108.50
In Byte it will be something like this,
10101|1001010010000000011000000000|1110111011
I have tried the following programs to do this
Server.java
public class Server extends Thread
{
private ServerSocket serverSocket;
public Server(int port) throws IOException
{
serverSocket = new ServerSocket(port);
//serverSocket.setSoTimeout(100000);
}
public void run()
{
while(true)
{
try
{
Socket server = serverSocket.accept();
byte Message[]=null;
DataInputStream in =
new DataInputStream(server.getInputStream());
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead;
byte[] data = new byte[16384];
while ((nRead = in.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
System.out.println("On this line"); //This doesnt get printed
buffer.flush();
data= buffer.toByteArray();
System.out.println(data);
String convertmsg = new String(data);
System.out.println("Msg converted "+convertmsg);
DataOutputStream out =
new DataOutputStream(server.getOutputStream());
System.out.println("below dataoutputstream");
out.write("Success".getBytes());
server.close();
}catch(SocketTimeoutException s)
{
System.out.println("Socket timed out!");
break;
}catch(IOException e)
{
e.printStackTrace();
break;
}
}
}
public static void main(String [] args)
{
int port = 4003;
try
{
Thread t = new Server(port);
t.start();
}catch(IOException e)
{
e.printStackTrace();
}
}
}
client
public class Client {
public static void main(String args[]) throws IOException
{
int userinput =1;
while(userinput==1)
{
String serverName = "192.168.0.8";
int port = 4003;
try
{
System.out.println("Connecting to " + serverName
+ " on port " + port);
Socket client = new Socket(serverName, port);
System.out.println("Just connected to "
+ client.getRemoteSocketAddress());
OutputStream outToServer = client.getOutputStream();
DataOutputStream out =
new DataOutputStream(outToServer);
System.out.println("above out.wirte()");
out.write("any msg".getBytes());
InputStream inFromServer = client.getInputStream();
DataInputStream in =
new DataInputStream(inFromServer);
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead;
System.out.println("converting array "+in);
byte[] data = IOUtils.toByteArray(in);
System.out.println(data);//This line doesnt get printed
//System.out.println("Server says " + in.readUTF());
client.close();
}catch(IOException e)
{
e.printStackTrace();
}
System.out.println("Enter userinput ");
DataInputStream dis = new DataInputStream(System.in);
String s = dis.readLine();
userinput = Integer.parseInt(s);
}
}
}
If i send data from client to server in bytes,it reads it and prints it.Also then the line "Enter userinput " gets printed and if the user enters '1' the program continues.
But the problem is this program given above. If i try to send data from server stating "success"(meaning the data has been converted from bytes to String successfully) then the program stucks and the cursor doesnt go below the line which are in comments "This line doesnt get printed".There is no error printed and none of the program terminates.I am new to socket programming and dont understand much about networking.
Any help will be truly appreciated.
You're reading the input until end of stream, but the peer isn't closing the connection, so end of stream never arrives.
I suggest you read and write lines, or use writeUTF() and readUTF().
What type of stream can I use to send a request message over a tcp socket to jabber.
I'm writing a string with xml format.
I cant use any libraries. It has to be pure java sockets.
the following is the code which i used. But the response for the second xml request is null
try {
Socket s = new Socket("195.211.49.6", 5222);
PrintWriter out = new PrintWriter(s.getOutputStream());
out.println("<stream:stream to='nimbuzz.com' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0'>");
out.flush();
BufferedReader reader = new BufferedReader(new InputStreamReader(s
.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
out.println("<iq type='set' xml:lang='en' id='terms' to='nimbuzz.com'><query xmlns='jabber:iq:auth'><username>username</username><password>password</password><resource>resource</resource></query></iq>");
out.flush();
reader = new BufferedReader(new InputStreamReader(s
.getInputStream()));
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
s.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
System.out.println(e.getLocalizedMessage());
}
this is what i have implemented in c#, it works quite fast too.
Socket m_socWorker;
try
{
m_socWorker = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
string ipString = "195.211.49.6";
string str2 = "5222";
int port = Convert.ToInt16(str2, 10);
IPEndPoint remoteEP = new IPEndPoint(IPAddress.Parse(ipString), port);
m_socWorker.Connect(remoteEP);
string page=string.Empty, page1=string.Empty, page2=string.Empty;
string s = "<stream:stream to='nimbuzz.com' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0'>";
byte[] bytes = Encoding.UTF8.GetBytes(s);
byte[] buffer = new byte[0x4b38];
m_socWorker.Send(bytes, bytes.Length, SocketFlags.None);
int count = 0;
count = m_socWorker.Receive(buffer, buffer.Length, SocketFlags.None);
page = page + Encoding.ASCII.GetString(buffer, 0, count);
byte[] buffer3 = new byte[0x4b38];
int num2 = 0;
num2 = m_socWorker.Receive(buffer3, buffer3.Length, SocketFlags.None);
page1 = page1 + Encoding.ASCII.GetString(buffer3, 0, num2);
if (page1.Replace("\"", "'").IndexOf("<stream:features><starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/><mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><mechanism>PLAIN</mechanism><mechanism>PLAIN TEXT</mechanism></mechanisms><register xmlns='http://jabber.org/features/iq-register'/></stream:features>", 0) != 0)
{
string str3 = "<iq type='set' xml:lang='en' id='Nimbuzz_Login' to='nimbuzz.com'><query xmlns='jabber:iq:auth'><username>username</username><password>password</password><resource>resource</resource></query></iq>";
byte[] buffer4 = new byte[0x30d40];
buffer4 = Encoding.UTF8.GetBytes(str3);
byte[] buffer5 = new byte[0x4b38];
m_socWorker.Send(buffer4, buffer4.Length, SocketFlags.None);
int num3 = 0;
num3 = m_socWorker.Receive(buffer5, buffer5.Length, SocketFlags.None);
page2 = Encoding.ASCII.GetString(buffer5, 0, num3);
string str4 = page2.Replace("\"", "'");
int num4 = 1;
}
}
catch (SocketException)
{
}
catch (Exception)
{
}
You are attaching a 2nd BufferedReader (InputStreamReader (...)) to your stream.
Probably the answer to your second request is being consumed and lost in the first buffer.
Try re-using your initial BufferedReader reader; to read the answer to the second message. Remember that XMPP is a single bi-directional stream, so all interaction happens through the same socket throughout the lifetime of your connection.
-- EDIT --
Q: How should the second request be like?
A: Editing your code to give you a starting point (not checked for compilation, just to give you the idea on how to proceed):
private static final int BUFFER_SIZE = 1024;
// Encapsulate the read process
private String readData(Reader reader) throws IOException {
StringBuilder result = new StringBuilder();
char[] buffer = new char[BUFFER_SIZE]; // [note1]
while (reader.ready()) { // [note2]
int charsRead = reader.read(buffer,0,BUFFER_SIZE-1));
if (charsRead > 0) {
result.append(buffer,0,charsRead);
}
}
return result.toString();
}
public void readStuff() {
try {
Socket s = new Socket("195.211.49.6", 5222);
PrintWriter out = new PrintWriter(s.getOutputStream());
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(s.getInputStream()));
out.println("<stream:stream to='nimbuzz.com' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0'>");
out.flush();
// Read out the data and print it to the console
System.out.println(readData(bufferedReader));
// Second request over the same socket
out.println("<iq type='set' xml:lang='en' id='terms' to='nimbuzz.com'><query xmlns='jabber:iq:auth'><username>username</username><password>password</password><resource>resource</resource></query></iq>");
out.flush();
// Read out the answer for the second result
System.out.println(readData(bufferedReader));
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
System.out.println(e.getLocalizedMessage());
}
}
Notes:
[1] This buffer can be reused across different requests. There's no actual need to recreate it every time this method is called. I left it there to provide you some anchoring with your C# code.
[2] You are checking for EOF in your code. This will potentially not happen in an XMPP connection. It's better to read the characters that are available in the stream until there're no more. Therefore I'm checking on reader.ready() instead of reader.read(...)>-1
See this question for further discussion on EOF: How do I recognize EOF in Java Sockets?