My C++ client shown below
#include "mbed.h"
#include <TCPSocket.h>
#include <EthInterface.h>
#include "EthernetInterface.h"
#include "string.h"
#include "ESP8266Interface.h"
ESP8266Interface wifi(D1, D0);
void ClearBuffer();
char rbuffer[300];
int rcount;
int main() {
printf("Main\n\r");
printf("Connecting...\n\r");
int ret = wifi.connect("ssid","password", NSAPI_SECURITY_WPA_WPA2);
if (ret != 0) {
printf("\r\n*** WiFi Connection error ***\r\n");
return -1;
}
printf("IP Address is %s\r\n", wifi.get_ip_address());
//create socket
TCPSocket sock;
sock.open(&wifi);
int ret2 = sock.connect("address", port);//ip of google cloud VM
if(ret2 != 0)
{
printf("*** Socket connection error ***\r\n");
return -1;
}
sock.set_blocking(false);
//sending to java server
char sbuffer[] = "Hello from client\r\n\r\n";
int scount = sock.send(sbuffer, sizeof sbuffer);
printf("sent %d [%.*s]\r\n", scount, strstr(sbuffer, "\r\n")-sbuffer, sbuffer);
//recieve from java server
rcount = sock.recv(rbuffer, sizeof rbuffer);
printf("recv %d [%.*s]\r\n", rcount, strstr(rbuffer, "\r\n")-rbuffer, rbuffer);
printf("Done\r\n");
// sock.close();
wifi.disconnect();
}
And the Java server
System.out.println("Just connected to " + server.getRemoteSocketAddress());
BufferedReader in = new BufferedReader(new InputStreamReader(server.getInputStream()));
Waiting for client on port 8082...
Hello from client
But when i try and send something back to C++ client like this:
PrintWriter out = new PrintWriter(new OutputStreamWriter(server.getOutputStream()));
String s = "Hello from server\0";
out.println(s);
out.flush();
C++ client code to receive:
rcount = sock.recv(rbuffer, sizeof rbuffer);
printf("recv %d [%.*s]\r\n", rcount, strstr(rbuffer, "\r\n")-rbuffer, rebuffed);
My output is:
sent 22 [Hello from client]
recv -3001 []
Can anybody help me figure out why the string I send back to the c client is not working?
Thank you.
strstr(), printf("%s...") etc. operate on NUL-terminated char arrays. Calling them on arrays that are not securely NUL-terminated is undefined behaviour, eg:
rcount = sock.recv(rbuffer, sizeof rbuffer);
printf("recv %d [%.*s]\r\n", rcount, strstr(rbuffer, "\r\n")-rbuffer, rebuffed);
try:
rcount = sock.recv(rbuffer, (sizeof rbuffer)-1);
if(rcount>0){
rbuffer[rcount]='\0';
printf("recv %d [%.*s]\r\n", rcount, strstr(rbuffer, "\r\n")-rbuffer, rebuffer);
}
else
if (rcount=0) (printf("Socket closed")
else
printf("Error on socket"); // get perror, errno, getLastError or whatever..
Related
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 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.
I have two apps, one written in Java that sends string, it looks like this:
import java.io.*;
import java.net.*;
public class Gniazdo{
public static void main(String[] args) throws IOException {
DataOutputStream dataOutputStream = null;
Socket socket = null;
String mes = "Test message";
try {
socket = new Socket("192.168.1.116", 4014);
dataOutputStream = new DataOutputStream(socket.getOutputStream());
dataOutputStream.writeChars(mes);
} catch (UnknownHostException e) {
System.err.print(e);
} finally {
if(socket != null) {
socket.close();
}
if(dataOutputStream != null) {
dataOutputStream.close();
}
}
}
}
and second one is written in C and runs on Raspberry Pi, that should receive string :
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <string.h>
int main(void) {
unsigned int port;
char bufor[1024];
int gniazdo, gniazdo2;
struct sockaddr_in adr, nadawca;
socklen_t dl;
printf("Enter port to listen : ");
scanf("%u", &port);
gniazdo = socket(AF_INET, SOCK_STREAM, 0);
adr.sin_family = AF_INET;
adr.sin_port = htons(port);
adr.sin_addr.s_addr = INADDR_ANY;
if (bind(gniazdo, (struct sockaddr*) &adr,
sizeof(adr)) < 0) {
printf("Bind failed.\n");
return 1;
}
if (listen(gniazdo, 10) < 0) {
printf("Listen failed.\n");
return 1;
}
printf("Waiting for connection ...\n");
while (gniazdo2 = accept(gniazdo,
(struct sockaddr*) &nadawca,
&dl)
)
{
// memset(bufor, 0, 1024);
recv(gniazdo2, bufor, 1024, 0);
printf("message from %s: %s\n", inet_ntoa(nadawca.sin_addr), bufor);
close(gniazdo2);
}
close(gniazdo);
}
and my output is:
Enter port to listen : 4014
Waiting for connection ...
message from 192.168.1.103:
message from 192.168.1.103:
message from 192.168.1.103:
message from 192.168.1.103:
Please could anyone tell me whats wrong?
Why i don't receive the message?
I even checked packets outgoing from my computer with Wireshark and they contains my message, but still don't know where I made mistake
1) Try calling writeBytes(String s) on the DataOutputStream.
2) Try calling flush on the DataOutputStream
(even though close should be calling flush anyway).
3) Try using PrintWriter to send the String
See
http://docs.oracle.com/javase/6/docs/api/java/io/PrintWriter.html#PrintWriter%28java.io.OutputStream,%20boolean%29
and this method in particular
http://docs.oracle.com/javase/6/docs/api/java/io/PrintWriter.html#write%28java.lang.String%29
4) Also, I think you should swap these two
if(socket != null) {
socket.close();
}
if(dataOutputStream != null) {
dataOutputStream.close();
}
printf is looking at 'bufor' as a char (8-bit), but java will write 16-bit UTF-16 characters. The first byte of the first character is 0. printf sees the 0 and thinks it's the end of the string. Try formatting the string to UTF-8 when you write it to the socket or reading it and printing it as a wchar.
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.
Hey guys, i've been searching for some info on sockets programming for a few hours right now and still can't understand how to solve a problem i have.
I've been asked to do the following :
The server receives an UDP datagram at the port 8080, sent from a client, in the datagram the client sends an array of chars that represents a number(9090)
The server will create a new socket, establish a TCP connection with the client at the port
9090.
Through the tcp connection, the server will read the a name, sent by the client.
We're asked to write a client able to do those tasks in C, the server is already done and is found in a .jar file
The program should run like this : ./client SERVER_NAME
and the server: java -jar server.jar
i got as far as this goes...with a think it covers the first part(sending the udp package) but not quite sure how to follow:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#define SERVERPORT "8080" // the port users will be connecting to
int main(int argc, char *argv[])
{
int sockfd;
struct addrinfo hints, *servinfo, *p;
int rv;
int numbytes;
if (argc != 2) {
fprintf(stderr,"usage: talker hostname\n");
exit(1);
}
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
if ((rv = getaddrinfo(argv[1], SERVERPORT, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return 1;
}
// loop through all the results and make a socket
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) == -1) {
perror("talker: socket");
continue;
}
break;
}
if (p == NULL) {
fprintf(stderr, "talker: failed to bind socket\n");
return 2;
}
int num = 9090;
num = htonl(num);
if ((numbytes = sendto(sockfd, num, sizeof(num), 0,
p->ai_addr, p->ai_addrlen)) == -1) {
perror("talker: sendto");
exit(1);
}
Does the java server provide any feedback you can use to verify the your UDP thus far? If so, I would verify and proceed as follows..
Setup a separate socket to make the TCP connection. There are many resources on the Internet showing how to do that (Google 'c tcp client example'). Since UDP is an unreliable best-effort protocol you will want to have a method for retrying the connection. One solution might be to loop, sending the UDP datagram and trying the TCP connection on the other socket until the connection is made (or some other time limit or maximum retry limit is reached).
// setup TCP socket to connect to your chosen port 'num'...
if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
// handle error
struct sockaddr_in tcpServAddr;
memset(&tcpServAddr, 0, sizeof(tcpServAddr));
tcpServAddr.sin_family = AF_INET;
tcpServAddr.sin_addr.s_addr = inet_addr(<insert server ip here>);
tcpServAddr.sin_port = htons(num);
const int iMaxTries = 10;
int iTryCount = 0;
bool bConnected = false;
while(!bConnected && (iTryCount < iMaxTries)) {
// using your bock from above:
if ((numbytes = sendto(sockfd, num, sizeof(num), 0,
p->ai_addr, p->ai_addrlen)) == -1) {
perror("talker: sendto"); // may want to output strerr(errno) for more information
break; // something is wrong if we can't send UDP. bail and figure that out
}
++iTryCount;
// try the TCP connection on the target port
if (connect(tcpSockFd, (struct sockaddr *) &tcpServAddr, sizeof(tcpServAddr)) == 0) {
bConnected = true;
} else {
// report error
}
}
if (bConnected) {
// send(...) name on tcpSockFd
}
// cleanup sockets
None of the above is tested, but hopefully it gives you some general direction.