i am making a program that sends a string from a Java client to a C server using WinSock2. I am using DataOutputStream to send the data through the socket.
The C server, acknowledges the bytes received, but when i try accessing the data, nothing is displayed.
SERVER
Socket socket = null;
DataOutputStream dataOutputStream = null;
DataInputStream dataInputStream = null;
try {
socket = new Socket("10.40.0.86", 2007);
dataOutputStream = new DataOutputStream(socket.getOutputStream());
dataInputStream = new DataInputStream(socket.getInputStream());
//dataOutputStream.writeUTF("How are you doing let us see what is the maximum possible length that can be supported by the protocal");
String line = "hey";
dataOutputStream.writeUTF(line);
dataOutputStream.flush();
//System.out.println(dataInputStream.readLine());
System.out.println((String)dataInputStream.readLine().replaceAll("[^0-9]",""));
//System.out.println(dataInputStream.readInt());
//System.out.println(dataInputStream.readUTF());
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
CLIENT
if (socket_type != SOCK_DGRAM)
{
retval = recv(msgsock, Buffer, sizeof(Buffer), 0);
printf("Server: Received datagram from %s\n", inet_ntoa(from.sin_addr));
}
output
Server: Received 5 bytes, data "" from client
BUFFER :
Server: Echoing the same data back to client...
BUFFER :
Server: send() is OK.
Your C code needs to understand the data format written by writeUTF() (see the Javadoc), or else more simply you need to use write(char[]) or write(byte[]) at the Java end.
Here is how I solved this :-)
dataOutputStream.write(line.getBytes());
Or to be more specific here is my code:
out.write(("Hello from " + client.getLocalSocketAddress()).getBytes());
Related
I'm finding a way to get an array, each component can have value between 0 and 255.
I'm using Android Studio and I received data from a socket. The following is my code.
try {
InetAddress IpAddress = InetAddress.getByName(remoteName);
myUpd_socket = new DatagramSocket(remotePort);
// Send connect message
String str = "connect request";
send_data = str.getBytes();
DatagramPacket send_packet = new DatagramPacket(send_data,str.length(), IpAddress, remotePort);
myUpd_socket.send(send_packet);
byte[] dataArray = new byte[1024];
DatagramPacket udp_packet = new DatagramPacket(dataArray,dataArray.length);
while (true) {
myUpd_socket.receive(udp_packet);
byte[] buff = new byte[udp_packet.getLength()];
System.arraycopy(dataArray,0,buff,0,buff.length);
}
} catch (SocketException e) {
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
I need to get the same data from the transmitter. There is no negative value in original data. But when I checked the received data, the buff has a lot of negative values. I made something wrong here.
I'm a newbie of Java and android. So I'm really grateful if someone can help me.
Thank.
Why not to use:
RECEIVE
Socket socket = ...
DataInputStream in = new DataInputStream(socket.getInputStream());
int length = in.readInt(); // read length of incoming message
if(length>0) {
byte[] message = new byte[length];
in.readFully(message, 0, message.length); // read the message
}
SEND
byte[] message = ...
Socket socket = ...
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
out.writeInt(message.length); // write length of the message
out.write(message); // write the message
bytes are signed in Java. If you want the unsigned value (as an int), use this: byteValue & 0xFF.
In the below code i am receiving data from the server but the String is not received completely "i should receive a sentence but each time i am receiving a segment of the sentence of different lengths"
uint8_t buf[1024];
unsigned int len = 0;
len = [inputStream read:buf maxLength:1024];
NSString *s;
if(len > 0) {
NSMutableData* data=[[NSMutableData alloc] initWithLength:0];
[data appendBytes: (const void *)buf length:len];
s = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"%#",s);
}
server side:
i am sending to the server using DataOutputStream
ServerSocket welcomeSocket=new ServerSocket(6789);
while(true){
Socket connectionSocket=welcomeSocket.accept();
DataOutputStream outToClient=new DataOutputStream(connectionSocket.getOutputStream());
outToClient.writeBytes("sign up accepted you can now sign in"+'\n');
Also what if i need to send a long text.
You aren't flushing your Stream. Try something like this
OutputStream outToClient = null;
try {
ServerSocket welcomeSocket = new ServerSocket(6789);
while (true) {
Socket connectionSocket = welcomeSocket.accept();
outToClient = new BufferedOutputStream(
connectionSocket.getOutputStream());
outToClient.write("sign up accepted you can now sign in\n"
.getBytes("UTF-8"));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (outToClient != null) {
try {
outToClient.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
if (outToClient != null) {
try {
outToClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
In addition to flushing the send side, the receive side is not safe.
TCP is a stream protocol, not a message protocol. You have to handle the message framing in the receiving side. In your case, you could keep reading until you receive the newline.
The network may split your message to several parts, rather arbitrarily when you look at it from the point of view of the receiver. It isn't really arbitrary, but there are many factors involved depending on the network topology. The receiver has to collect these parts until a complete message is received. This is called framing. One could use the newline for framing, or prepend the length and keep reading until satisfied, or any other solution that lets the receiver know what to expect.
I'm building a Java client application which needs to send a message to a server and receive a response afterwards. I can send the message successfully, the problem is that I can't get the response because I get an IO exception ("Socked is closed") when trying to read the 'BufferedReader'.
This is my code, so far:
public class MyClass {
/**
* #param args the command line arguments
*/
#SuppressWarnings("empty-statement")
public static void main(String[] args) {
JSONObject j = new JSONObject();
try {
j.put("comando", 1);
j.put("versao", 1);
j.put("senha", "c4ca4238a0b923820dcc509a6f75849b");
j.put("usuario", "1");
j.put("deviceId", "1");
} catch (JSONException ex) {
System.out.println("JSON Exception reached");
}
String LoginString = "{comando':1,'versao':1,'senha':'c4ca4238a0b923820dcc509a6f75849b','usuario':'1','deviceId':'1'}";
try {
BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in));
Socket clientSocket = new Socket("10.1.1.12", 3333);
System.out.println("Connected to the server successfully");
PrintWriter outToServer = new PrintWriter(clientSocket.getOutputStream(),true);
outToServer.println(j.toString());
outToServer.close();
System.out.println("TO SERVER: " + j.toString());
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String resposta = inFromServer.readLine();
System.out.println("FROM SERVER: " + resposta);
clientSocket.close();
} catch (UnknownHostException ex) {
System.out.println("Could not connect to the server [Unknown exception]");
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
}
}
I know that the socket is being closed because of the OutToServer.close() but closing the stream is the only way to send the message. How should I approach this situation?
flush() is not the case when it comes with new PrintWriter(, true).
The real problem is that you are closing the PrintWriter outToServer which wraps the underlying InputStream, again, came from the Socket.
When you close the outToServer you're closing the whole socket.
You have to use Socket#shutdownOutput().
You don't even have to close the output if you want to keep the socket's in/out channels for further communications.
flush() when you are done with any writeXXX. Those writeXXX practically don't mean you sent those bytes and characters to other side of the socket.
You may have to close the output, and output only, to signal the server that you sent all you had to send. This is really a matter of the server-side socket's desire.
final Socket socket = new Socket(...);
try {
final PrintStream out = new PrintStream(socket.getOutputStream());
// write here
out.flush(); // this is important.
socket.shutdownOutput(); // half closing
// socket is still alive
// read input here
} finally {
socket.close();
}
Try to call outToServer.flush()
That will try to flush the data from the buffer, although it still not guarantees that it will be sent.
I got to implement a chat in my application. Connection to a server is made using sockets. I should register to that server and the server will aknowledge that with a reply.
I have implemented this in a single method where I send the command using a BufferedWriter, and then start reading from the input stream until it tells me there is no more data.
I read properly the server reply. However, I never get the negative value from the second in.read call and thus my method stays blocked in the while loop (in the conditionnal statement where I make that call).
How should this be done with sockets? I usually do that with files or other input streams without problem.
If I should read only the bytes I am supposed to read, does that mean that I either have to:
Know in advance the length of the server response?
or make the server send a code to notify it has finished to send its response?
Currently I am doing the following:
private String sendSocketRequest(String request, boolean skipResponse) throws ChatException {
if (!isConnected()) openConnection();
try {
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(
socket.getOutputStream()), 2048);
out.append(request);
out.flush();
out = null;
} catch (IOException e) {
LogHelper.error("Unable to send socket request: " + request, e);
throw new ChatException("Unable to send socket request: " + request, e);
}
try {
BufferedReader in = new BufferedReader(new InputStreamReader(
socket.getInputStream()), 2048);
StringBuffer response = new StringBuffer();
char[] buffer = new char[2048];
int charsRead = -1;
// >>>>>>>> This is where it gets blocked <<<<<<<<<
while ((charsRead = in.read(buffer)) >= 0) {
if (charsRead > 0) response.append(new String(buffer, 0, charsRead));
}
return response.toString();
} catch (IOException e) {
LogHelper.error("Unable to read socket response: " + request, e);
throw new ChatException("Unable to read socket response: " + request, e);
}
}
Connection to the server is made with the following method:
public synchronized void openConnection() throws ChatException {
try {
socket = new Socket(Constants.API_CHAT_SERVER_ADDRESS, Constants.API_CHAT_SERVER_PORT);
socket.setKeepAlive(true);
LogHelper.debug("CHAT >> Connected to the chat server: " + Constants.API_CHAT_SERVER_ADDRESS);
} catch (UnknownHostException e) {
LogHelper.error("Unable to open chat connection", e);
throw new ChatException("Unable to open chat connection", e);
} catch (IOException e) {
LogHelper.error("Unable to open chat connection", e);
throw new ChatException("Unable to open chat connection", e);
}
}
The amount of data to be sent/received over a socket based connection is protocol dependend and not known to the TCP/IP stack, but only to the application layer.
The protocol used is developer dependend ... ;-) so coming to your questions:
If I should read only the bytes I am supposed to read, does that mean that I either have to:
Know in advance the length of the server response?
Yes, this is one possibility.
or make the server send a code to notify it has finished to send its response?
Also yes, as this is another possibility. Common markers are \n or \r\n. The NUL/'\0' character also might make sense.
A third option is to prefix each data chunk with a constant number of bytes describing the amount of bytes to come.
Instead of dealing with bytes, maybe it's simpler handling instances of ad-hoc classes, like - for instance - a Message class:
The server:
// Streams
protected ObjectInputStream fromBuffer = null;
protected ObjectOutputStream toBuffer = null;
// Listening for a new connection
ServerSocket serverConn = new ServerSocket(TCP_PORT);
socket = serverConn.accept();
toBuffer = new ObjectOutputStream(socket.getOutputStream());
fromBuffer = new ObjectInputStream(socket.getInputStream());
// Receiving a new Message object
Message data = (Message)fromBuffer.readObject();
The client then sends a message by simply:
// Sending a message
Message data = new Message("Hello");
toBuffer.writeObject(data);
Message can be as complex as needed as long as its members implement Serializable interface.
I am trying to send a file (an image sent as a byte array) with the client and then the server should receive said byte array to make further use of it. However when I click on the "send" to send the image the file transfer starts (as I get a sentImage.jpg in my Desktop) but it gets stuck for some reason I can't figure out and the image never gets correctly sent.
Here's the part that receives from the server (it already accepted the connection):
public void run(){
try {
byte[] receivedData = new byte[1024];
BufferedInputStream bis = new BufferedInputStream(client.getInputStream());
// while(bis.read() != -1){
s.acquireUninterruptibly();
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("C:\\Users\\Admin\\Desktop\\sentImage.jpg"));
while ((incoming = bis.read(receivedData)) != -1) {
bos.write(receivedData, 0, incoming);
}
s.release();
n.release();
bis.close();
bos.flush();
// }
} catch (IOException e) {
e.printStackTrace();
}
}
and the client is sending here:
public void sendImageResult() {
new Thread(new Runnable() {
public void run() {
try {
int inside = 0;
Socket socket = new Socket("localhost", 4444);
File myImageFile = new File("C:\\Users\\Admin\\Desktop\\test.jpg");
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(myImageFile));
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream( ));
byte[] byteArray = new byte[1024];
while ((inside = bis.read(byteArray)) != -1){
bos.write(byteArray,0,inside);
}
bis.close();
bos.flush();
} catch (UnknownHostException ex) {
System.out.println("No se pudo establecer la conexión.");
ex.printStackTrace();
} catch (FileNotFoundException fnf){
fnf.printStackTrace();
} catch(IOException ioe){
ioe.printStackTrace();
}
}
}).start();
}
It does not appear that the OutputStream (bos) that is used to write to disk is being closed. This could lead to unexpected results.
As jt said, the OutputStream writing to disk is not being closed, but neither is the OutputStream being used to send the data, nor is the Socket being closed from the sending side. The sending side may be buffering the data at the tcp level, waiting for more bytes before sending the last packet. You are calling flush, but that can be ignored, it's not guaranteed to work like you expect. Another thing to try is calling shutdownOutput on the Socket and seeing if that forces it to flush. You can also try setTcpNoDelay(true) when you open the Socket. If none of that works, get a tcp trace program (I like tcpdump) and use it to see if the packets are actually being sent, it will at least narrow it down to either the send or receive end of things.