I suspect this has to do with endianness but I'm not sure how to fix it. I have a C++ client telling a Java server how many bytes it's about to send where the Java server just calls readInt() on the input stream. Then the server goes onto read the rest of the data.
At the moment if the C++ server calls:
char l = '3';
BytesSent = send( Socket, &l, 1, 0 );
Then the corresponding Java side is:
int lBytesSent = m_InDataStream.readInt();
m_AckNack = new byte[lBytesSent];
m_InDataStream.read(m_AckNack)
Bytes lBytesSent tends to be some massive value which then just throws an exception when it comes to creating the array (not surprisingly)
The C++ socket is simply opened up with:
Socket = socket(AF_INET, SOCK_STREAM, 0);
Option = 1000;
setsockopt(Socket, SOL_SOCKET, SO_RCVTIMEO, (char *) &Option, sizeof(Option));
server.sin_family = AF_INET;
server.sin_port = htons(Port);
server.sin_addr.s_addr = INADDR_ANY;
memset(&(server.sin_zero), '\0', 8);
connect(Socket, (sockaddr*)&server, sizeof(server));
And the Java side:
ServerSocket listener = new ServerSocket(port);
Socket server;
server = listener.accept();
Removing the error checking for clarity.
Any suggestions would be great
Many Thanks
Mark
Try running the number through htonl before sending it (on the C++ side):
long x = htonl(42); /* x now contains 42 represented in network byte order */
Related
I'm unable to send a UTF-8 string from a C# server to a Java client due to an EOF error in the client. How do I properly configure the C# server? I assume the error lies there because this client works with the Java server shown below.
Java client's receive function does this (this also works if I receive from a Java server, shown below):
DataInputStream dataInputStream = new DataInputStream(socket.getInputStream()); //The constructor initialises a field, using the socket object.
StringBuilder inputMessage = new StringBuilder();
inputMessage.append((String) dataInputStream.readUTF());
Desired C# server:
static async Task Main(string[] args)
{
TcpListener server = new TcpListener(IPAddress.Any, 34567);
server.Start();
byte[] bytes = new byte[4096];
byte[] responseBytes;
using (var client = await server.AcceptTcpClientAsync()){
using(var tcpStream = client.GetStream())
{
await tcpStream.ReadAsync(bytes, 0, bytes.Length);
var playerNumber = Encoding.UTF8.GetString(bytes);
Console.WriteLine("Player " + playerNumber + " connected."); //java client to server works.
StringBuilder outputMessage = new StringBuilder("Some output");
responseBytes = Encoding.UTF8.GetBytes(outputMessage.ToString());
await tcpStream.WriteAsync(responseBytes, 0, responseBytes.Length); //This doesn't work...
}
server.Stop();
}
}
The error:
java.io.EOFException
at java.base/java.io.DataInputStream.readFully(DataInputStream.java:201)
at java.base/java.io.DataInputStream.readUTF(DataInputStream.java:613)
at java.base/java.io.DataInputStream.readUTF(DataInputStream.java:568)
at Client.Connection.Receive(Connection.java:26)
at Client.Main.lambda$main$0(Main.java:30)
at com.sun.javafx.application.PlatformImpl.lambda$startup$5(PlatformImpl.java:271)
at com.sun.glass.ui.Application.invokeAndWait(Application.java:464)
at com.sun.javafx.tk.quantum.QuantumToolkit.runToolkit(QuantumToolkit.java:366)
at com.sun.javafx.tk.quantum.QuantumToolkit.lambda$startup$10(QuantumToolkit.java:280)
at com.sun.glass.ui.Application.lambda$run$1(Application.java:153)
Interestingly, a Java server doing this works:
DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
StringBuilder outputMessage = new StringBuilder("Some output");
dataOutputStream.writeUTF(outputMessage.toString());
dataOutputStream.flush();
EDIT
This is received from the working Java server. The "bytearr" contains 100 bytes that I am using for my message and 100 bytes that are 0 (they come after my message). The "chararr" correctly sees the first 100 bytes as something meaningful and the last 200 bytes as '\u0000':
This is received form the non-working C# server. It seems to start two bytes in compared to the correct version and also it's "chararr" contains only thousands of '\u0000':
DataInputStream's readUTF reads a special data format, it is not a general purpose method for reading a sequence of UTF-8 bytes. Most notably, it expects an initial sequence of bytes specifying the length of the stream.
I found the answer here. Changing the way the Java client reads to this, works:
byte[] buff = dataInputStream.readAllBytes();
String str = new String(buff, "UTF-8");
I have got a Java Server and a C# Client. And I'm really certain something goes wrong with the outputstreamer on the client or inputstream on the server.
byte[] arr = IOUtils.toByteArray(is,14);
PrintWriter out = new PrintWriter(os, true);
out.print("Received "+ new String(arr,"UTF-8"));
out.flush();
out.close();
"is" in this case is the Input Stream Variable. Coming from Socket.getInputStream().
Removing the length of the stream (14 in this case) makes the system time-out. The client does not get any respons except: "Read Failure"
The client side consists of a C# program
byte[] start = getIdentifier();
byte[] end = Encoding.UTF8.GetBytes(toSend);
byte[] arr = start.Concat(end).ToArray();
//Arr variable is a couple of strings smashed together and transformed into a byte[]
networkStream.Write(arr, 0, arr.Length);
networkStream.Flush();
StreamReader streamReader = new StreamReader(networkStream);
result = streamReader.ReadToEnd();
I actually tried writing to the Server with a BinaryWriter too, but that didn't work either. If I know what the length of the data is that will be send, I can fix the problem. But I do not know how to send the length of the stream to the server.
I've tried using Available() to see how much there was to read, but for some reason that sometimes was 0. As if the data wasn't been sent by the client yet.
Any ideas of how to fix the freezing?
EDIT:
I think I understand how the streaming works now.
At first I did this on the client side:
var length = BitConverter.GetBytes(arr.Length);
Array.Reverse(length);
Then on the server side I put this piece of code:
/* Get Input Data Length */
byte[] arr = IOUtils.toByteArray(is, 4);
int length = (arr[0] << 24) & 0xff000000 |
(arr[1] << 16) & 0x00ff0000 |
(arr[2] << 8) & 0x0000ff00 |
(arr[3] << 0) & 0x000000ff;
/* Get Input Data */
arr = IOUtils.toByteArray(is, length);
#Andreas your mention of the big-endian byte order made it clear how to send the length to the server
I'm programming a Java server and a C++ client with the purpose of send Strings between them. But I am having so much problems with C++...
On my server, I create the server socket that listens on. After connection I expect a client message with:
entrada = new DataInputStream(socketCliente1.getInputStream());
mensajeRecibido=entrada.readUTF();
In my client I create the socket and connect as follows:
SOCKET ConnectSocket = INVALID_SOCKET;
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
struct addrinfo *result = NULL, *ptr = NULL, hints;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
iResult = getaddrinfo("192.168.0.17", DEFAULT_PORT, &hints, &result);
ptr = result;
ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
freeaddrinfo(result);
The problem comes here ... How do I send the String to the Java server?
And if I write in the Java server as:
output = new DataOutputStream (socketCliente1.getOutputStream ());
salida.writeUTF ("Hello");
How could receive with my C++ client?
If it's possible I would like not to touch the code in Java, because it has to work with Java clients too (which I have not had any problems to implement).
I don't have so much idea about C, so please, if it's possible tell me details like the libraries to use in the answer.
I have a simple server written in Java, that just sends an Integer to a connected client. I have a client written in C, that connects to the server and prints out the received Integer.
My problem is that the result varies. About half of the times executing the client I get the correct result (234), but other times I get 8323072.
This is the server:
class TCPServer {
public static void main(String args[]) throws Exception {
ServerSocket welcomeSocket = new ServerSocket(6789);
while(true)
{
Socket connectionSocket = welcomeSocket.accept();
System.out.println("welcomeSocket.accept() called");
DataInputStream inFromClient = new DataInputStream(connectionSocket.getInputStream());
DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());
outToClient.writeInt(234);
}
}
}
And this is the client:
int main(int argc, char *argv[])
{
if(argc != 4){
printUsage();
return;
}
char* serverIP = argv[1];
char* serverPortC = argv[2];
char* integerToSendC = argv[3];
int serverPort = atoi(serverPortC);
int integerToSend = atoi(integerToSendC);
int socketDesc = socket(AF_INET, SOCK_STREAM, 0);
if(socketDesc < 0) {
printf("Error when creating socket\n");
return;
}
struct sockaddr_in serverAddr;
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(serverPort);
inet_pton(AF_INET, serverIP, &serverAddr.sin_addr);
int connection = connect(socketDesc, (struct sockaddr*) &serverAddr, sizeof serverAddr);
if(connection < 0) {
printf("Error when establishing connection\n");
return;
}
char intBuffer[4];
if(recv(socketDesc, intBuffer, sizeof intBuffer, 0) == -1){
printf("Error while receiving Integer\n");
}
int receivedInt = ntohl(*((int *) &intBuffer));
printf("Received int: %d\n", receivedInt);
close(socketDesc);
}
Thanks in advance for any help!
Edit:
So in the end I did something like this, just for anybody who has the same problem:
while(receivedBytes < 4){
int readBytes = read(receiverSocket, &intBuffer, (sizeof intBuffer) - receivedBytes, receivedBytes);
receivedInteger += (intBuffer << (8*receivedBytes));
receivedBytes += readBytes;
}
Can you be sure you have received sizeof intBuffer bytes on the client side? No you can not, as recv() might return less bytes then requested.
Mod you code to loop around recv() as long as less bytes then requested have been received and no error occurred.
Note that recv()ing 0 bytes indicates the connection had been closed by the other side.
Also make sure the server side sends in network byte order.
Also^2: It is good idea to initialise variables (intBuffer here), at least during the development phase, will say: prior to the tuning phase.
Your problem could be because of the sub-boundaries of the various data types.
In Java, 4 bytes are assigned to int and 2 bytes for a short.
In C, 4 bytes are for long and 2 bytes for int.
This means Java int -> C long and Java short -> C int.
Now it depends on where your priorities lie.
If you want to perform an intense mathematical calculation in Java and send the result over socket to C, I recommend you do Java int -> C long or
If you want to just send small numbers and have the intense calculation done in C, do the Java short -> C int conversion.
Hope that helped.
I'm writing a server program in c, and the client is on android platform which uses java language.Now I have a trouble to send char array from the server to the client,which means the client can get the data but can not decode it.I think it maybe because of the problem of data types or encoding differences.Can anyone give me some ideas,Thanks a lot!
Here is my code of server side:
char buf[MAXSIZE];
memset(buf, 0, MAXSIZE);
int n_write;
strcpy(buf, "0008200050005001");
n_write = Write(confd, buf, strlen(buf));
if (n_write <= 0)
{
fputs("Write error in send_matrix_and_position\n", stderr);
close(confd);
return -1;
}
And here is Java code:
mSocket = new Socket(HOST, PORT);
mIn = mSocket.getInputStream();
mOut = mSocket.getOutputStream();
byte[] lengthByte = new byte[4];
mIn.read(lengthByte);
for(byte b : lengthByte)
{
System.out.println(b + "");
}
You are sending 16 characters, but you read only four. Aren't you getting the data
48
48
48
56? These are the codes of the first four characters sent.
Try checking what values you get at the client when you read the char array, you might probably be doing br.readline(); see if this prints the characters??
You need to debug and check, then you might come up with some way.