C++ server Java client socket [duplicate] - java

Hey guys, here is my code.
int main() {
char buffer[BUFSIZE];
// define our address structure, stores our port
// and our ip address, and the socket type, etc..
struct sockaddr_in addrinfo;
addrinfo.sin_family = AF_INET;
addrinfo.sin_port = htons(PORT);
addrinfo.sin_addr.s_addr = INADDR_ANY;
// create our socket.
int sock;
if ( (sock = socket(addrinfo.sin_family, SOCK_STREAM, 0)) < 0) {
cout << "Error in creating the socket.";
}
// bind our socket to the actual adress we want
if (bind(sock, (struct sockaddr*)&addrinfo, sizeof(addrinfo)) != 0) {
cout << "Error in binding.";
}
// open the socket up for listening
if (listen(sock, 5) != 0) {
cout << "Error in opening listener.";
}
cout << "Waiting for connections...." << endl;
char *msg = "Success! You are connected.\r\n";
// continuously accept new connections.. but no multithreading.. yet
while(1) {
struct sockaddr_in client_addr;
socklen_t sin_size = sizeof(client_addr);
if(int client = accept(sock, (struct sockaddr*)&client_addr, &sin_size)) {
cout << "Recived new connection from " << inet_ntoa(client_addr.sin_addr) << endl;
send(client, msg, strlen(msg), 0);
while(1) {
send(client, buffer, recv(client, buffer, BUFSIZE, 0), 0);
cout << buffer << endl;
strcpy(buffer, "");
}
} else {
cout << "Error in accepting new connection." << endl;
}
}
close(sock);
return 0;
}
Now, I'm very new to sockets, Im just sort of trying to get a feel for them but I do have some experience with sockets in PHP. I'm using telnet via putty on my linux machine to test this, I don't know if thats causing any issues but the server is outputting some strange characters and I don't know why. I think it has something to do with the buffer, but I'm not really sure. I can send things like "hi" to the server via telnet and it outputs them just fine and sends them back to me but when I send things like "hoobla" it starts the funky character stuff. Any suggestions would be helpful!
Thanks in advance!

You're getting rubbish printed out because recv does not null-terminate your buffer.
The important section in the below code is:
int num = recv(client,buffer,BUFSIZE,0);
if (num < 1) break;
send(client, ">> ", 3, 0); // <<-- Nice to have.
send(client, buffer, num, 0);
buffer[num] = '\0'; // <<-- Really important bit!
if (buffer[num-1] == '\n') // <<-- Nice to have.
buffer[num-1] = '\0'; // <<-- Nice to have.
cout << buffer << endl;
which will properly terminate your buffer before trying to print it, as well as remove the trailing newline if present (and allow the client to distinguish between input and echoed lines).
This one (a complete program) works a little better:
using namespace std;
#include <iostream>
#include <sys/socket.h>
#include <arpa/inet.h>
#define BUFSIZE 1000
#define PORT 1234
int main() {
char buffer[BUFSIZE];
// define our address structure, stores our port
// and our ip address, and the socket type, etc..
struct sockaddr_in addrinfo;
addrinfo.sin_family = AF_INET;
addrinfo.sin_port = htons(PORT);
addrinfo.sin_addr.s_addr = INADDR_ANY;
// create our socket.
int sock;
if ( (sock = socket(addrinfo.sin_family, SOCK_STREAM, 0)) < 0) {
cout << "Error in creating the socket.";
return -1;
}
// bind our socket to the actual adress we want
if (bind(sock, (struct sockaddr*)&addrinfo, sizeof(addrinfo)) != 0) {
cout << "Error in binding.";
return -1;
}
// open the socket up for listening
if (listen(sock, 5) != 0) {
cout << "Error in opening listener.";
return -1;
}
char *msg = "Success! You are connected.\r\n";
// continuously accept new connections.. but no multithreading.. yet
while(1) {
cout << "Waiting for connections...." << endl;
struct sockaddr_in client_addr;
socklen_t sin_size = sizeof(client_addr);
if(int client =
accept(sock, (struct sockaddr*)&client_addr, &sin_size))
{
cout << "Recieved new connection from "
<< inet_ntoa(client_addr.sin_addr) << endl;
send(client, msg, strlen(msg), 0);
while(1) {
int num = recv(client,buffer,BUFSIZE,0);
if (num < 1) break;
send(client, ">> ", 3, 0);
send(client, buffer, num, 0);
buffer[num] = '\0';
if (buffer[num-1] == '\n')
buffer[num-1] = '\0';
cout << buffer << endl;
strcpy(buffer, "");
}
} else {
cout << "Error in accepting new connection." << endl;
}
}
close(sock);
return 0;
}
On the client side:
$ telnet 127.0.0.1 1234
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
Success! You are connected.
hello
>> hello
my name is pax
>> my name is pax
and you?
>> and you?
<CTRL-D>
Connection closed by foreign host.
and, on the server side:
$ ./testprog
Waiting for connections....
Recived new connection from 127.0.0.1
hello
my name is pax
and you?
Waiting for connections....

The problem is that buffer is not guaranteed to contain a string-terminating null character. Add the line buffer[BUFSIZE-1] = '\0' just before your cout << buffer.
Even better, actually record how many bytes were received, and use that information to determine if you overran your buffer.

Related

Android - Connect() / Socket(ip, port) does NOTHING

EDIT: I've managed to connect the server from a python client, which means that there's a problem in the ANDROID connection. I've been trying to figure it out in the last 2 hours- the connect() function nor the socket() function, does nothing! I'm freaking out.
PROBLEM: ,
I'm working on an android application, which basically communicates with a server that runs on my laptop in c++ (my laptop OS is Windows 8).
My client connects to the server only when I'm connected to my home network. When I'm connected to other networks, my client throws an exception:
** The server computer connected with a cable **
java.net.SocketTimeoutException: failed to connect to /192.168.43.60 (port 5898) after 3000ms
The Android code:
Thread th = new Thread(new Runnable() {
public void run() {
Socket client_socket = new Socket(); // Creates a socket and binds it to available port.
Log.d("INFO", "Created Socket");
for (int retries = 0; retries < 3; retries++) {
try {
client_socket.connect(new InetSocketAddress("127.0.0.1", 5898), 3000); // Connect to the server.
break;
} catch (java.net.SocketTimeoutException e) {
Log.d("INFO", "Connect() failed with an error.");
e.printStackTrace();
continue;
}
}
}
Log.d("INFO", "Connecting to server on " + ProtCodes.serverIP + ":" + ProtCodes.serverPORT);
};
th.start();
th.join();
Server side:
using namespace std;
int main(int argc, char* argv[])
{
Server* server;
SOCKADDR_IN sockAddrIn;
CLIENT_INFO client_info;
int iResult = 0, number_of_connected_clients = 0, clientLen = sizeof(sockAddrIn);
std::list<SOCKADDR_IN>* connected_clients; //list of connected clients SOCKADDRS structs (for ip & port)
t1 = clock();
try { //validates the PORT argument
if (atoi(argv[0]) > 1024 && atoi(argv[0]) < 65535)
server = new Server(atoi(argv[0]));
else
server = new Server(DEFAULT_PORT);
}catch (...){
server = new Server(5898);
}
iResult = listen(server->getSocket(), SOMAXCONN);
if (iResult == SOCKET_ERROR) {
printf("listen failed with error: %d\n", WSAGetLastError());
closesocket(server->getSocket());
WSACleanup();
return TRUE;
}
cout << endl << "#Server_log: Connected!" << endl;
cout << "#Server_log: Launching MySQL server, version: " << string(mysql_get_client_info()) << endl;
cout << "#Server_log: Server is up running on " << get_ipv4_address() << ":" << ntohs(server->get_server_info().sin_port) << endl;
cout << "#Server_log: Waiting for requests..." << endl;
cout << "*******************************************" << endl << endl;
std::thread server_command(&handle_server_commands, server); //thread for server commands
server_command.detach();
/* Accept a client socket */
while (number_of_connected_clients < MAX_CONNECTIONS)
{
memset(&sockAddrIn, 0, sizeof(sockAddrIn));
clientLen = sizeof(sockAddrIn);
ClientSocket = accept(server->getSocket(), (struct sockaddrn*)&sockAddrIn, &clientLen);
if (ClientSocket == INVALID_SOCKET)
{
printf("accept failed with error: %d\n", WSAGetLastError());
continue;
}
/* Print connected client info */
client_info.ip = inet_ntoa(sockAddrIn.sin_addr);
client_info.port = ntohs(sockAddrIn.sin_port);
cout << endl;
get_current_time();
cout << "Client connected on " << client_info.ip << " : " << client_info.port << " !" << endl;
cout << endl << ">> ";
connected_clients = server->get_connected_clients();
connected_clients->push_back(sockAddrIn); //push client SOCKADDR struct into server's clients list
std::thread a(&(handle_user_requests), ClientSocket, server, client_info); //thread for clients requests handle
a.detach();
}
closesocket(ClientSocket);
closesocket(server->getSocket());
WSACleanup();
}
Thanks a lot!
Idan

c - client / java - server - client reading strange things

Server:
public static void getListOfFiles(String path, DataOutputStream outToClient) throws IOException
{
// Directory path here
//String path = ".";
String files;
try
{
File folder = new File(path);
File[] listOfFiles = folder.listFiles();
String sendOver = "";
for (int i = 0; i < listOfFiles.length; i++)
{
files = listOfFiles[i].getAbsolutePath();
sendOver = sendOver + "!" + files;
}
outToClient.writeBytes(sendOver + "\n");
}
catch (Exception e)
{
outToClient.writeBytes("There was an error with the path, please try again. \n" );
}
}
public static void getDate(DataOutputStream outToClient) throws IOException
{
outToClient.writeBytes(Calendar.getInstance().getTime().toString() + '\n');
}
public static void getUsers(DataOutputStream outToClient) throws IOException
{
outToClient.writeBytes("User logged in: "+ System.getProperty("user.name") + "\n");
}
}
Client:
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
int main()
{
int sock, bytes_recieved;
char send_data[1024],recv_data[1024];
struct hostent *host;
struct sockaddr_in server_addr;
bytes_recieved = 1024;
host = gethostbyname("localhost");
sock = socket(AF_INET, SOCK_STREAM,0);
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(3324);
server_addr.sin_addr = *((struct in_addr *)host->h_addr);
bzero(&(server_addr.sin_zero),8);
connect(sock, (struct sockaddr *)&server_addr,sizeof(struct sockaddr));
char *temp = '\n';
while(1)
{
printf("Enter Command...\n");
gets(send_data);
strcat(send_data, "\n");
send(sock,send_data,strlen(send_data), 0);
if(send_data[0] == 'Q' && send_data[1] == 'U' && send_data[2] == 'I' && send_data[3] == 'T')
{
printf("Quiting...");
break;
}
//printf("\nSend Data :");
recv_data[bytes_recieved] = '\0';
bytes_recieved = recv(sock,recv_data,1024,0);
//fflush(stdin);
printf("\nRecieved data = %s" , recv_data);
recv_data[bytes_recieved] = '\0';
}
}
Essentially, the server side recieves everything correctly (I have debugged it), however the client must not be reading correctly-
Here are some examples from my console on the client side:
test
Recieved data = Error wEnter Command...**<---- What The??**
Recieved data = ith command: TEST_c.dylibEnter Command... **<---- What The??**
Recieved data = Error with command: dylibEnter Command... **<---- What The??**
Recieved data = Error with command: Enter Command... **<---- What The??**
I am writing back
outToClient.writeBytes("Error with command: " + capitalizedSentence + "\n" );
When I get the above. Hopefully someone is better versed in C.
One bug (not sure is there are more):
You do:
bytes_recieved = 1024;
char send_data[1024],recv_data[1024];
recv_data[bytes_recieved] = '\0'; // <--- HERE YOU ARE WRITING OUT OF BOUNDS
bytes_recieved = recv(sock,recv_data,1024,0);
Try:
recv_data[bytes_recieved - 1] = '\0';
bytes_recieved = recv(sock,recv_data,1023,0);
Also, unless all messages are 1023 bytes long. You may have to add the \0 at the end of the string, instead of the end of buffer.
Finally, you should have a look at the manual for the usage of read. http://linux.die.net/man/2/recv.
It is possible, that you are not using the flag you intend to use. You can see a way of determining the number of bytes available in the buffer here: https://stackoverflow.com/a/3054519/828193
Hope that helps.

Writing To C++ Console Application Spawned Within Java App Under Windows

How can I send string data from Java to a C++ console application under Windows? I am trying to do this:
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(proc.getOutputStream()));
String o = ...;
proc.getOutputStream().write(o.getBytes());
But I never see it on the C++ side when I do this:
ReadFile(stdin_h,buf, sizeof(buf), &bytes, 0)
ReadFile never returns.
What follows is further elaboration and sample code.
I have written a simple C++ console (Win32) application which reads from STDIN and performs actions based on input.
Now I want to write a Java application to "drive" the C++ application. The Java applicaton should:
Start the C++ application using Runtime.exec()
Write string data to the C++ app's STDIN
Repeat until it's time to die.
My Java application seems to be working, but the C++ application never receives any data on STDIN.
Here is the C++ application:
int main()
{
ofstream f("c:\\temp\\hacks.txt");
HANDLE stdin_h = GetStdHandle(STD_INPUT_HANDLE);
DWORD file_type = GetFileType(stdin_h);
if( file_type != FILE_TYPE_CHAR )
return 42;
f << "Pipe" << endl;
for( bool cont = true; cont; )
{
char buf[64*1024] = {};
DWORD bytes = 0;
if( ReadFile(stdin_h,buf, sizeof(buf), &bytes, 0) )
{
string in(buf,bytes);
cout << "Got " << in.length() << " bytes: '" << in << "'" << endl;
f << "Got " << in.length() << " bytes: '" << in << "'" << endl;
if( in.find('Q') )
cont = false;
}
else
{
cout << "Err " << GetLastError() << " while reading file" << endl;
f << "Err " << GetLastError() << " while reading file" << endl;
}
}
}
And here is the Java side:
public static void main(String[] args) {
Runtime rt =Runtime.getRuntime();
try {
Process proc = rt.exec("c:\\dev\\hacks\\x64\\debug\\hacks.exe");
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(proc.getOutputStream()));
int a = 0;
while(a < 5)
{
String o = (a == 4 ? "Q\n" : "A\n");
proc.getOutputStream().write(o.getBytes());
System.out.println("Wrote '" + o + "'");
++a;
}
try {
proc.waitFor();
// TODO code application logic here
} catch (InterruptedException ex) {
Logger.getLogger(Java_hacks.class.getName()).log(Level.SEVERE, null, ex);
}
} catch (IOException ex) {
Logger.getLogger(Java_hacks.class.getName()).log(Level.SEVERE, null, ex);
}
}
The Java side seems to be working correctly, but I'm not ever receiving the strings on the C++ side.
Am I doing something wrong here? How can I send string data from Java to a C++ console application under Windows?
Why are you not flushing the output stream on the Java side after writing 5 strings?
proc.getOutputStream().flush();

Ensuring no packet loss between TCP client and server

I am writing a Java TCP client which sends chunks of data to a C server. The client-server worked very well on my development PC. This code upon deployment on a hardware board showed packet loss. I only have the logs with me and I know that the server did not receive all packets.
I do not have the hardware to test. Therefore, at the first level, I want to be very sure client code does send all the required data.
Here is my code(the client part in Java). How do I make sure this is done? Is there some resend commands with timings etc?
Socket mySocket = new Socket("10.0.0.2",2800);
OutputStream os = mySocket.getOutputStream();
System.out.println(" Sending 8 byte Header Msg with length of following data to Server");
os.write(hdr, 0, 8);
os.flush();
System.out.println(" Sending Data ");
start = 0;
for(int index=0; index < ((rbuffer.length/chucksize)+1); index++){
if(start + chucksize > rbuffer.length) {
System.arraycopy(rbuffer, start, val, 0, rbuffer.length - start);
} else {
System.arraycopy(rbuffer, start, val, 0, chucksize);
}
start += chucksize ;
os.write(val,0,chucksize);
os.flush();
}
Here is the C snippet which receives this data:
while ((bytes_received = recv(connected, rMsg, sizeof(rMsg),0)) > 0){
if (bytes_received > 0) // zero indicates end of transmission */
{
/* get length of message (2 bytes) */
tmpVal = 0;
tmpVal |= rMsg[idx++];
tmpVal = tmpVal << 8;
tmpVal |= rMsg[idx++];
msg_len = tmpVal;
len = msg_len;
//printf("msg_len = %d\n", len);
printf("length of following message from header message : %d\n", len);
char echoBuffer[RCVBUFSIZE] ;
memset(echoBuffer, 0, RCVBUFSIZE);
int recvMsgsize = 0;
plain=(char *)malloc(len+1);
if (!plain)
{
fprintf(stderr, "Memory error!");
}
for( i = RCVBUFSIZE; i < (len+RCVBUFSIZE); i=i+RCVBUFSIZE){
if(i>=len){
recvMsgSize = recv(connected, echoBuffer, (len - (i-RCVBUFSIZE)), 0);
memcpy(&plain[k], echoBuffer, recvMsgSize);
k = k+recvMsgSize;
}
else{
recvMsgSize = recv(connected, echoBuffer, RCVBUFSIZE, 0);
memcpy(&plain[k], echoBuffer, recvMsgSize);
k = k+recvMsgSize;
}
}
}//closing if
}//closing while
First of all there is no such thing as packet loss in TCP/IP. This protocol was designed to reliably send a stream of bytes in correct order. So the problem must be with your application or the other side.
I am not really in a mood to analyze this whole arraycopy() madness (C anyone?), but why aren't you just sending the whole rbuffer in one go through BufferedOutputStream?
OutputStream os = new BufferedOutputStream(mySocket.getOutputStream());
and then:
os.write(rbuffer);
Believe me, BufferedOutputStream is doing the exact same thing (collecting bytes into chunks and sending them in one go). Or maybe I am missing something?
I changed the C side program in the following way and it now works:
printf("length of following message from header message : %d\n", len);
plain=(char *)malloc(len+1);
if (!plain)
{
fprintf(stderr, "Memory error!");
}
memset(plain, 0, len+1);
int remain = len;
k= 0;
while (remain){
int toGet = remain > RCVBUFSIZE ? RCVBUFSIZE : remain;
remain -= toGet;
int recvd = 0;
while(recvd < toGet) {
if((recvMsgSize = recv(connected, echoBuffer, toGet-recvd, 0)) < 0){
printf("error receiving data\n");
}
memcpy(&plain[k], echoBuffer, recvMsgSize);
k += recvMsgSize;
printf("Total data accumulated after recv input %d\n", k);
recvd += recvMsgSize;
}
}

C socket server, Java socket client : BLOCKING!

I am pasting my code for a simple socket server in C and a Java client.
I use write method sending character by character in Java. However after the chunk of characters are sent(here, 'h', 'e', 'y') , the Java client is send blocked as the C server does not reply to it :(
I am assuming there is some problem with sending a null character(from the Java write) that would stop the recv at the C side.
Any help would be greatly appreciated.
C server:
#include <stdio.h> /* standard in and output*/
#include <sys/socket.h> /* for socket() and socket functions*/
#include <arpa/inet.h> /* for sockaddr_in and inet_ntoa() */
#include <stdlib.h>
#include <string.h>
#include <unistd.h> /* for close() */
int main(int argc, char *argv[]){
int sock, connected, bytes_received, true = 1;
char recv_data;
char replyBuffer[32];
struct sockaddr_in server_addr,client_addr;
int sin_size;
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("Socket");
exit(1);
}
if (setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&true,sizeof(int)) == -1) {
perror("Setsockopt");
exit(1);
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(2400);
server_addr.sin_addr.s_addr = INADDR_ANY;
bzero(&(server_addr.sin_zero),8);
if (bind(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
perror("Unable to bind");
exit(1);
}
if (listen(sock, 5) == -1) {
perror("Listen");
exit(1);
}
printf("\nTCPServer Waiting for client on port 2400");
while(1){
sin_size = sizeof(client_addr);
connected = accept(sock, (struct sockaddr *)&client_addr,&sin_size);
printf("\n Got a connection from (%s , %d)",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));
while ((bytes_received = recv(connected,&recv_data,1,0)) > 0){
printf("\nrecv= %c\n", recv_data);
}
int success = 1;
sprintf(replyBuffer, "%d", success);
printf("reply buffer = %s\n", replyBuffer);
if (send(connected, replyBuffer, strlen(replyBuffer), 0) == -1)
perror("send() failed");
success = 0;
close(connected);
}
}
Java Client:
import java.net.*;
import java.io.*;
public class Client1
{
public static void main(String[] args) throws IOException {
if (args.length < 2) {
System.err.println("Usage: java Client1 <IP address> <Port number>");
System.exit(0);
}
BufferedReader in = null;
OutputStream out = null;
Socket sock = null;
try {
sock = new Socket(args[0], Integer.parseInt(args[1]));
out = sock.getOutputStream();
in = new BufferedReader(new InputStreamReader(sock.getInputStream()));
String line = "hey";
String responseline = null;
char[] strArray;
strArray = line.toCharArray();
while (true) {
for( int index = 0; index < strArray.length; index++){
out.write(strArray[index]);
}
out.flush();
System.out.println("data sent " );
System.out.println("val returned"+in.readLine());
}
}
catch (IOException ioe) {
System.err.println(ioe);
}
finally {
if (in != null)
in.close();
if (out != null)
out.close();
if (sock != null)
sock.close();
}
}
}
from javadoc for BufferedReader.readLine()
Read a line of text. A line is considered to be terminated by any one of a line feed ('\n'), a carriage return ('\r'), or a carriage return followed immediately by a linefeed.
That's why it blocks (no lf, no cr, no crlf)
[edit]
You need to create an EOL indicator that the C program understands (just like readLine() in the java client. Let that indicator be '\n' (for consistency if nothing else)
In Client.java, append '\n' to your sent string.
In tst.c, test for '\n', when it's received, break from the recv() loop
[/edit]
Your assumption of the problem is correct. The recv call will always return a value greater than zero. I suggest using a special character to designate the end of the text and terminating the recv() loop when that character is read.
In my opinion there is an error of your server code.If you compile your server code on linux, there be an error. The type of sin_size should be socklen_t.
or you will see an error information "invalid conversion from int* to socklen_t"
client change to
out.write(line.getBytes());
server change to
char recv_data[32];
recv(connect,recv_data,32,0);

Categories