Sending int via socket from Java to C - strange results - java

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.

Related

A socket with c server over java socket

My assignment requiers me to write an server in c but client in java. I need to send some integer to my client as instructions. They can connected smoothly but my java client cannot Receive the integer send from c server. there is only two possibilities: my c server did not send the Number out OR my client does not Receive the integer correctly. The c server is able to loop as I type in since the printf and scanf is executed while nothing happends on the client side.
I am stuck here, any help will be appreciate!
=========================================================================
UPDATE:
I correct the main class in java where the class name of the client into dotClient, and my client was able to conncected and read the inputs from the server.
I have try to send an 'int' directly in the server side, but When the client(java) use DataInputStream.ReadInt(), it returns a randomly big number as if the size of int in c and size of int in java is not matched.When I use a c client to do the same job, it works normal. So there is Hidden Problem for using dataInputStream directly with a c server, as I tried readShort() and ReadLong() as well.
As suggested, I use bufferReader.
And send string in server side, and perse it into int in client.
it works.
hère is my updated c code
#define PORT 55555
int main(int argc, char const *argv[])
{
int server_fd, new_socket, valread;
struct sockaddr_in address;
int opt = 1;
int addrlen = sizeof(address);
char buffer[1024];
int returnSend = 0;
// Creating socket file descriptor
if (
(server_fd = socket(AF_INET, SOCK_STREAM, 0))
== 0)
{
perror("socket failed");
exit(EXIT_FAILURE);
}
printf("%s\n", "Socket created!");
// Forcefully attaching socket to the port 8080
if (setsockopt(server_fd, SOL_SOCKET,
SO_REUSEPORT, &opt, sizeof(opt)))
{
perror("setsockopt");
exit(EXIT_FAILURE);
}
printf("Socket attached!\n");
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons( PORT );
// Forcefully attaching socket to the port 8080
if (bind(server_fd,
(struct sockaddr *)&address,
sizeof(address))<0)
{
perror("bind failed");
exit(EXIT_FAILURE);
}
printf("socket binded!\n");
if (listen(server_fd, 3) < 0)
{
perror("listen");
exit(EXIT_FAILURE);
}
printf("socket listened!\n");
if ((new_socket = accept(server_fd,
(struct sockaddr *)&address,
(socklen_t*)&addrlen))<0)
{
perror("accept");
exit(EXIT_FAILURE);
}// Socket formulated !
do{
fgets(buffer, sizeof(buffer), stdin);
returnSend = write(new_socket , buffer , strlen(buffer));
printf("Sending: %sReturn returnSend: %d.\n", buffer,returnSend);
} while (1);
return 0;
}
hère is my updated java client
import java.net.*;
import java.io.*;
public class dotClient
{
// initialize socket and input output streams
private Socket echoSocket= null;
private BufferedReader input = null;
// constructor to put ip address and port
public dotClient(String address, int port)
{
// establish a connection
try
{
echoSocket = new Socket(address, port);
System.out.println("Connected");
input =
new BufferedReader(
new InputStreamReader(echoSocket.getInputStream()));
}
catch(UnknownHostException u)
{
System.out.println("exception 1: "+u);
}
catch(IOException i)
{
System.out.println("exception 2: "+i);
}
int number = 0;
String line = "";
// keep reading until read neagaive integer
try
{
while ((line = input.readLine()) != null)
{
number = Integer.parseInt(line);
System.out.println("String is :"+line);
System.out.println("number is :"+number);
}
}
catch(IOException i)
{
System.out.println("Exception 3: "+i);
}
// close the connection
try
{
input.close();
out.close();
echoSocket.close();
System.out.println("Connection closed!");
}
catch(IOException i)
{
System.out.println("Exception 4: "+i);
}
}
public static void main(String args[])
{
dotClient client = new dotClient("192.168.0.3", 55555);
}
}
In your main method you are creating a Client instance but your class is called dotClient. You might want to ensure you are creating an instance of your class dotClient. Otherwise I agree with the previous comments and would suggest BufferedReader and BufferedWriter/PrintWriter for the IO.
Do any of your try blocks catch an exception on the client? Check the return value of send(new_socket , &number , size(number) , 0 ); on the server to make sure the data was actually sent for more info checkout http://man7.org/linux/man-pages/man2/send.2.html.

Java Socket Read returns Strange Characters on second read

I've got a C++ Socket Server that sends a JSON String to a Java Client. For the Java Part I'm using the following Code:
BufferedReader in = new BufferedReader(new InputStreamReader(soc.getInputStream()));
while((inString = in.readLine()) != null) {
Log.i("JSON", inString);
C++ Code:
WSADATA wsa;
SOCKET s, new_socket;
struct sockaddr_in server, client;
int c;
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) { return false; }
if ((s = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) { return false; }
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(13377);
if (bind(s, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR) { return false; }
listen(s, 3);
c = sizeof(struct sockaddr_in);
new_socket = accept(s, (struct sockaddr *)&client, &c);
if (new_socket == INVALID_SOCKET) { return false; }
while (listenSocket) {
if(...){
char sendData[] = "hallo";
send(new_socket, sendData, sizeof(sendData), NULL);
}
When receiving the First Time everything is received as planned. However, the second time It only prints out Questions Marks in Squares "�". Is that because I'm sending a char array of 2048 chars that might only contain a lower amount than that or what could the problem be?
You are reading lines, i.e. character data terminated by \n, \r, or \r\n, as specified for BufferedReader.readLine(), but what you are sending isn't lines, it is null-terminated C strings. So you won't receive anything at all until the sender closes the connection, and then you will get a string containing who knows what where the nulls were.
You also aren't error-checking the result of send().
I think you should not send unnecessary data either way, so in your case only send the string with the following \0 or better and usually the default way the length of bytes and after that the data without \0 and only read a single string not a complete line.
Also be aware of the byte order (litte or big endian) when reading an integer as the data size for example.
I'm sure there is more documentation about how Java expects strings to be encoded for a socket connection or you have to read the raw bytes and convert it to a Java string yourself.

C server and java client

I created a C server and a java client. I was sending a command like ls through the client and server should execute it. However read in c server is still waiting for input. how to solve this problem.
Java client
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
class HelloWorld
{
public static void main(String... abc) {
try
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Enter ip and port : ");
String ip ;
String p;
String ss;
int port;
ip = br.readLine();
p = br.readLine();
port = Integer.parseInt(p);
Socket s = new Socket(ip,port);
OutputStream os = s.getOutputStream();
PrintWriter pw = new PrintWriter(os);
Scanner in = new Scanner(System.in);
ss = in.nextLine();
pw.print(s);
pw.flush();
pw.close();
}
catch(Exception e){
System.out.println("ERROR!!!");}
}
}
here is the c server.
#include"Headers.h"
void comm(char * s_port)
{
int sockfd, newsockfd, portno;
socklen_t clilen;
char buffer[MAXBUFFER];
char newbuffer[MAXBUFFER];
char var[MAXBUFFER] = " > file.txt";
int n;
struct sockaddr_in serv_addr, cli_addr;
FILE *fp = NULL;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = atoi(s_port);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
error("ERROR on binding");
listen(sockfd,5);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd,(struct sockaddr *) &cli_addr,&clilen);
if (newsockfd < 0)
error("ERROR on accept");
while (1)
{
bzero(buffer,1024);
n = read(newsockfd,buffer,1024);
if (strcmp(buffer , "exit\n") == 0)
break;
if (n < 0) error("ERROR reading from socket");
printf("Here is the message: %s\n",buffer);
strcpy(newbuffer,"");
if (buffer[strlen(buffer) - 1] == '\n')
buffer[strlen(buffer) - 1] = '\0';
strcat(newbuffer, buffer);
strcat(newbuffer, var);
printf("%s",newbuffer);
system(newbuffer);
break;
if (n < 0) error("writing to socket");
}
close(newsockfd);
close(sockfd);
}
n = read(newsockfd,buffer,1024);
if (strcmp(buffer , "exit\n") == 0)
break;
You forgot to implement a protocol. You can't just read an arbitrary bunch of bytes from the connection and then treat it as a message. TCP has no conception of a message. If you want to send and receive messages, you have to define what you mean by a "message" and write code to send and receive that implements that definition.
There are probably other problems with your code, but this defect is so severe and so fundamental, you really need to fix it first.
If your definition of a message is "a sequence of ASCII characters not including a zero byte or a newline terminated by a newline", then you need to write code to receive such a sequence. You can't just call read and expect it to find the message boundaries since it has no idea that you use newline as a message boundary.
The main problem with your code is the way you handle strings in C.
Your server seems to assume that you are sending UTF-8 encoded strings over the network but strings in Java are encoded in UTF-16 by default. You will also need a way to ensure that each message buffer only contains valid Unicode characters. Each character in a Unicode string can use multiple bytes and you might get partial sent characters on the server side.
You have a small typo in the java program:
pw.print(s);
s is the socket, so you are sending s.toString().
I think you mean:
pw.print(ss);
Also, you need to decide on a message protocol, just as #DavidSchwartz points out.
Some useful links:
Protocol types
Understanding and designing socket message protocols

Java DataInputStream readInt() from C++ Client getting huge value

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 */

Increasing data transfer speed on simple TCP client/socket

I have a homework assignment to create a simple data transfer mechanism with a client/server TCP socket pair by redirecting standard I/O. I actually have it working, but when I try to transfer large files (say ~5g) the speed slows down dramatically. I am using BufferedInputStream and BufferedOutputStream, and I think that perhaps there is some optimization I can make there. The code for my server is:
private static final int BUF_SIZE = 2047;
public static void main(String[] args) throws IOException{
/*
* Attempt to parse command line arguments.
* #require args[0] is an int
*/
int port = 0;
try {
port = Integer.parseInt(args[0]);
} catch(NumberFormatException e) {
System.err.println("Port must be an integer in range 0 - 65535.");
System.exit(-1);
}
/*
* Bind server socket to specified port number and wait for request.
* #require port >= 0 && port <= 65535
*/
ServerSocket welcomeSocket = null;
welcomeSocket = new ServerSocket(port);
System.out.println("Now listening on port: " + port);
/*
* Accept connection from client socket.
*/
Socket connectionSocket = null;
connectionSocket = welcomeSocket.accept();
System.out.println("Client made connection");
BufferedInputStream input;
BufferedOutputStream output;
if(System.in.available() > 0) {
input = new BufferedInputStream(System.in, BUF_SIZE);
output = new BufferedOutputStream(
connectionSocket.getOutputStream(), BUF_SIZE);
} else {
input = new BufferedInputStream(
connectionSocket.getInputStream(), BUF_SIZE);
output = new BufferedOutputStream(System.out, BUF_SIZE);
}
int place;
while((place = input.read()) != -1)
output.write(place);
input.close();
output.close();
welcomeSocket.close();
connectionSocket.close();
}
The client code is essentially the same. I have tried using different buffer sizes, including the default (by not specifying a buffer size), but they are all running at approximately the same speed. Any pointers on how I can increase my performance?
Thank you for your time!
while((place = input.read()) != -1)
You're reading one byte at a time from the buffer. The overhead of calling this method millions of times is rather large.
I would suggest reading more than one byte into a buffer with the other version (and writing the same way):
public int read(byte[] b,
int off,
int len)
Example:
byte[] myBuffer = new byte[BUF_SIZE];
while((place = input.read(myBuffer, 0, BUF_SIZE)) != 1)
output.write(myBuffer, 0, place);
you are reading and sending a byte at a time which is not efficient, you should read blocks of data (idle size would be the disk hardware buffer size).
of course, the disk should be your bottle neck here it takes time to read 5G form disk.

Categories

Resources