C server and java client - java

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

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.

Ending of "messages" exchanged between client and server sockets

Java server socket
In the following code:
https://docs.oracle.com/javase/tutorial/networking/sockets/examples/KnockKnockServer.java
import java.net.*;
import java.io.*;
public class KnockKnockServer {
public static void main(String[] args) throws IOException {
if (args.length != 1) {
System.err.println("Usage: java KnockKnockServer <port number>");
System.exit(1);
}
int portNumber = Integer.parseInt(args[0]);
try (
ServerSocket serverSocket = new ServerSocket(portNumber);
Socket clientSocket = serverSocket.accept();
PrintWriter out =
new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(clientSocket.getInputStream()));
) {
String inputLine, outputLine;
// Initiate conversation with client
KnockKnockProtocol kkp = new KnockKnockProtocol();
outputLine = kkp.processInput(null);
out.println(outputLine);
while ((inputLine = in.readLine()) != null) {
outputLine = kkp.processInput(inputLine);
out.println(outputLine);
if (outputLine.equals("Bye."))
break;
}
} catch (IOException e) {
System.out.println("Exception caught when trying to listen on port "
+ portNumber + " or listening for a connection");
System.out.println(e.getMessage());
}
}
}
when the server sends its response to the client socket, it writes to the "PrintWriter" "out" using the "println()" method (line 63).
I have tried using the "print()" method instead.
In the "println()" case, the client socket receives the message properly.
In the "print()" case, the client socket doesn't receive anything.
Is this normal?
Is it required to send an EOF, a CR LF (in my case) (10 and 13 ASCII characters) at the end of the message?
Is it documented somewhere?
Winsock
In the following code:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms737591%28v=vs.85%29.aspx
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
// Need to link with Ws2_32.lib, Mswsock.lib, and Advapi32.lib
#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")
#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT "27015"
int __cdecl main(int argc, char **argv)
{
WSADATA wsaData;
SOCKET ConnectSocket = INVALID_SOCKET;
struct addrinfo *result = NULL,
*ptr = NULL,
hints;
char *sendbuf = "this is a test";
char recvbuf[DEFAULT_BUFLEN];
int iResult;
int recvbuflen = DEFAULT_BUFLEN;
// Validate the parameters
if (argc != 2) {
printf("usage: %s server-name\n", argv[0]);
return 1;
}
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed with error: %d\n", iResult);
return 1;
}
ZeroMemory( &hints, sizeof(hints) );
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
// Resolve the server address and port
iResult = getaddrinfo(argv[1], DEFAULT_PORT, &hints, &result);
if ( iResult != 0 ) {
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return 1;
}
// Attempt to connect to an address until one succeeds
for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) {
// Create a SOCKET for connecting to server
ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype,
ptr->ai_protocol);
if (ConnectSocket == INVALID_SOCKET) {
printf("socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
// Connect to server.
iResult = connect( ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
if (iResult == SOCKET_ERROR) {
closesocket(ConnectSocket);
ConnectSocket = INVALID_SOCKET;
continue;
}
break;
}
freeaddrinfo(result);
if (ConnectSocket == INVALID_SOCKET) {
printf("Unable to connect to server!\n");
WSACleanup();
return 1;
}
// Send an initial buffer
iResult = send( ConnectSocket, sendbuf, (int)strlen(sendbuf), 0 );
if (iResult == SOCKET_ERROR) {
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
printf("Bytes Sent: %ld\n", iResult);
// shutdown the connection since no more data will be sent
iResult = shutdown(ConnectSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
// Receive until the peer closes the connection
do {
iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
if ( iResult > 0 )
printf("Bytes received: %d\n", iResult);
else if ( iResult == 0 )
printf("Connection closed\n");
else
printf("recv failed with error: %d\n", WSAGetLastError());
} while( iResult > 0 );
// cleanup
closesocket(ConnectSocket);
WSACleanup();
return 0;
}
the "send()" method is used.
Does it implicitly send an EOF (a CR LF sequence for example) to the server socket at the end of the message passed as an argument?
Is it documented somewhere?
Is it part of the socket implementation?
Note that, I am not adding a EOF (CR LF for example) at the end of the message.
I'm ending the message with a trailing '\0' character.
When a "message" (an array of characters) is sent from a socket endpoint to another socket endpoint, does the message have to be ended with some kind of EOF? It appears to me now that it doesn't.
There is no general need to send an EOF sign in java socket communication, BUT
if your client uses InputStream.readLine() to read the servers answer, than this is normal, because
readLine() blocks until a line has been completely read (until \n \r or \r\n found) or the socket is closed by the server.
But in this example, the socket is not closed by the server, because the server is waiting for the clients answer and if the client is waiting for the end of line, you have a deadlock.
when the server sends its response to the client socket, it writes to the "PrintWriter" "out" using the "println()" method
PrintWriter is line buffered. See the Javadoc.
I have tried using the "print()" method instead.
If you don't write a line it won't flush. Call flush() afterwards. But you shouldn't use PrintWriter over a network, as it swallows exceptions you need to know about. Use BufferedWriter.
In the "println()" case, the client socket receives the message properly.
Because it's line-buffered, so there was an auto-flush.
In the "print()" case, the client socket doesn't receive anything.
Because it's line-buffered so there wasn't an auto-flush.
Is this normal?
Yes.
Is it required to send an EOF, a CR LF (in my case) (10 and 13 ASCII characters) at the end of the message?
No.
Is it documented somewhere?
Yes, in the Javadoc for PrintWriter.

How to properly send data via sockets between java and c?

I am currently trying to send strings via sockets between Java and c. I am able to either send a String to the client (c) from the server (java), or vice versa, but not BOTH, which is how I need to communicate between the two. In my c (client) code, as soon as I insert the read portion, the code haults.
Here are my two portions of code. It is safe to assume the connection between the sockets is successful.
java:
private void handshake(Socket s) throws IOException{
this.out = new PrintStream(s.getOutputStream(), true);
this.in = new BufferedReader(new InputStreamReader(s.getInputStream()));
String key = in.readLine(); //get key from client
if(!key.equals(CLIENTKEY)){
System.out.println("Received incorrect client key: " + key);
return;
}
System.out.println("received: " + key);
System.out.println("sending key");
out.println("serverKEY"); //send key to client
System.out.println("sent");
}
c:
int n;
n = write(sockfd,"clientKEY",9);
if (n < 0)
{
perror("ERROR writing to socket");
exit(1);
}
n = read( sockfd,recvBuff,255 );
if (n < 0)
{
perror("ERROR reading from socket");
exit(1);
}
printf("Here is the message: %s\n",recvBuff);
Modify your C send code:
char clientKey[] = "clientKEY\n"
n = write(sockfd,clientKey, strlen(clientKey));
It's better to use a variable for clientKey and then call strlen so you don't have to count char's manually. As Jiri pointed out, Java's readLine function is probably expecting a newline char that it's never getting so it hangs.
It seems to me that the C/C++ server sends a clientKEY message to the Java client. The Java client reads a line, i.e. waits till it receives the \n character from the C/C++ server. However, it is never sent by the C/C++ server and so the Java client waits... forever.

Sending int via socket from Java to C - strange results

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.

Categories

Resources