I am trying to send an array of strings over a socket and receive it on the other end.
Here is my client side ( side sending the data ) :
char* client_hello[] =
{
"Type client_hello",
"Version SSLv3.0",
"Session ID 1",
"Random 1as2#3%$h&KF(*)JAGG&(#H%A$D#J*##",
"Cipher-Suites TLS_RSA_WITH_RC4_128_SHA",
"Compression null(0)"
};
SendBytes = send(sock, client_hello, 6, 0);
This is my Server side ( side receiving the data ):
int inMsgLen = recvfrom(clntSock, inMsg, 1024, 0,(struct sockaddr *)&clntAddr, (socklen_t*)&clntAddrLen);
if (inMsgLen < 0) {
//printf("Error in recvfrom() errno=%d\n", errno);
continue;//exit(1);
}else if (inMsgLen > 1024) {
printf("Received message too long (size=%d)\n", inMsgLen);
exit(1);
}else{
printf("Received Message: %s\n", inMsg);
}
inMsg is declared as char inMsg[1024];
This is what the output is on the server side :
Received Message: +?
What am I doing wrong ? How can I send/receive the entire client_hello array ?
I am trying to send an array of strings over a socket and receive it on the other end.
But the code is sending the first six bytes of an array of char* (as mentioned by WhozCraig in a comment to the question):
SendBytes = send(sock, client_hello, 6, 0);
the receiving side is reading the pointer addresses and treating them as strings, hence the junk.
To correct, send each string in turn but you will need to create a protocol that defines the beginning and end of a string as the bytes are written and read from sockets as streams, not some notion of message. For example, prefixing each string with its length (a sequence of digits terminated by a new-line character would be one simple option) followed by the actual string:
18\nSession ID 124\nCompression null(0)0\n
The receiving end would read to the new-line character, convert what was read to an int, allocate a buffer to contain the string (remembering space for the null terminator) and then read that number of char from the socket. A length of zero could be used to terminate the transfer of the list of strings.
Note that a call to send() may result in only a part of the requested data being sent. The code needs to cater for this by keeping track of the number of bytes send so far and indexing into the buffer being sent.
If you try to make a loop, using "for" to send... maybe is possible to server understand. Making client_hello[i], line by line..
Related
Hi I'm trying to create a simple username/password read and write between my Server and my Client application. Currently my Client side is working perfectly. The issue I am having is inside my Server side. When I enter a username on the Client side it is captured by my Server correctly. See the following code:
void authenticate_process(int cli_sockfd){
/* Authentication Process */
write(cli_sockfd, "USN", 3);
char *username;
username = recv_msg(cli_sockfd);
printf("[DEBUG] Client username is %s.\n", username);
write(cli_sockfd, "PSW", 3);
char *password;
password = recv_msg(cli_sockfd);
printf("[DEBUG] Client Password is %s.\n", password);
}
The problem is for example the user types "Johnabscaras" as the username then the code places the last "ras" into what is the password variable. My recv_msg function looks like the following:
/* Reads a message from the server socket. */
char *recv_msg(int sockfd)
{
int length;
char *msg;
msg = (char*) malloc (9);
/* All messages are 9 bytes. */
int n = read(sockfd, msg, 9);
return msg;
}
As the username and password is never larger than 9 bytes it is set for this. But I have found out that upon first entering the username if you type more that 9 characters the extra characters will be amended to the password variable. If you type less than 9 characters the code skips over and the password variable is immediately set to " " for some reason. Can someone please explain and show me how to fix this?
It looks like you're using a stream socket (SOCK_STREAM, i.e. TCP). A stream socket is basically (from the point of view of your program) just a bidirectional pipe.
There is no concept of "messages" beyond what your application imposes. The socket just sends and receives a single, long stream of bytes. write(fd, "foo", 3); write(fd, "bar", 3); has the same effect as write(fd, "foobar", 6);. It's sending the same bytes in the same order.
If you want your streams to transfer multiple separate messages, you have to encode those message boundaries somehow.
For example, you could decide that every message is exactly 100 bytes long and then always send/receive exactly 100 bytes.
Or you could mark the end of a message with an explicit terminator (such as '\0'). The receiving code would then have to loop until it sees a '\0'.
Or you could send a length field as the first part of each message; that way the receiving code knows in advance how many bytes it needs to allocate and read.
This comment in your code indicates that you chose option 1:
/* All messages are 9 bytes. */
But apparently the sending code has a bug because it tries to transmit a message of more than 9 bytes, which of course is then interpreted as multiple messages. If the client sends 12 bytes, then that's a message of 9 bytes followed by another (incomplete) message of 3 bytes. "Currently my Client side is working perfectly"? No, it isn't; at least not if your receiving code is correct.
Another issue is
printf("[DEBUG] Client username is %s.\n", username);
%s expects a C string, i.e. a nul-terminated sequence of characters. username has no NUL terminator (unless the client decided to explicitly send a '\0' byte as part of the message). In fact, users of recv_msg have no way of telling how much data was received. If it's always exactly 9 bytes,
printf("%.9s", username);
would work, but recv_msg doesn't make sure that this is the case:
int n = read(sockfd, msg, 9);
It simply ignores n, so it's possible for all or parts of msg to be uninitialized and the calling code cannot tell.
I am sending a file through TCP, and have the server sending a message containing "END_OF_MESSAGE" to alert the client that they have received the whole file and can close the socket. The file is being sent, and the client receives the "END_OF_MESSAGE" string, however, when I use strcmp to compare the received information to "END_OF_MESSAGE", it never says that they match. I have tried strncmp and memcmp but am confused as to why strcmp does not tell me the strings match.
Code snippets:
Server:
char endMessage[MESSAGESIZE] = "END_OF_MESSAGE";
if ((send(clntSocket, endMessage, sizeof endMessage, 0))!= sizeof endMessage) DieWithError("Sending failed");
The above code snippet does get sent.
Client:
if ((bytesRcvd = recv(sock, echoBuffer, RCVBUFSIZE - 1, 0)) <= 0)
DieWithError("recv() failed or connection closed prematurely");
totalBytesRcvd += bytesRcvd; /* Keep tally of total bytes */
echoBuffer[bytesRcvd] = '\0'; /* Terminate the string! */
if (!(strcmp(echoBuffer, "END_OF_MESSAGE")==0)){
printf(echoBuffer); /* Print the echo buffer */
printf("\n");
}else{
break; //break out of while loop
}
the strcmp of the echoBuffer and "END_OF_MESSAGE" never returns 0, even though "END_OF_MESSAGE" is what I am sending from the server..I have tried strncmp to compare the first 3 characters ("END") to no avail.
Note: when I print out the echoBuffer, the very last one does print out END_OF_MESSAGE which is just adding to my confusion.
Does anyone have any insights into what I am doing wrong?
Thank you.
am sending a file through TCP, and have the server sending a message containing "END_OF_MESSAGE" to alert the client that they have received the whole file and can close the socket.
Why? Just close the socket. That will tell the client exactly the same thing..
What you're attempting is fraught with difficulty. What happens if the file contains END_OF_MESSAGE? You're going to need an escape convention, and an escape for the escape, and inspect all the data when both sending and receiving.
The actual problem that you're seeing is that END_OF_MESSAGE can arrive along with the last bit of the file, so it isn't at the start of the buffer.
But it's all pointless. Just close the socket.
I am trying to learn client server model in Linux and I have setup two C files namely server.c and client.c. These are the code snippets that I seem to have problems with.
server.c code snippet
char* message = "<query>\n";
write(client_socket_filedescriptor, message, sizeof(message));
client.c code snippet
char* message = "<query>\n";
read(socket_filedescriptor, buffer, sizeof(buffer));
printf("%s", buffer);
printf("\n\n");
printf("%s", message);
Now when I run my server and then when I run my client, I expect the printf statements to print the same strings that is <query>\n, but I keep getting different outputs for buffer and message variables.
The output looks a bit like this when I run client code.
Output image
As you see, these two strings are different. I am trying to simulate a typical TCP handshake and I want to make sure that these two strings are same and then client will start writing or doing something with that server. But I am having this trivial problem. Could anyone tell my how to resolve it? I plan to use strcmp to compare buffer and message variables, but as it stands now, strcmp doesn't return 0 since these are different strings afterall.
You are ignoring the count returned by read(). It can be -1, indicating an error, or zero, indicating end of stream, or a positive number, indicating how many bytes were received. You cannot assume that read() fills the buffer, or that a single send() or write() corresponds to a single recv() or read().
In detail:
write(client_socket_filedescriptor, message, sizeof(message));
You are only sending four bytes, the size of the pointer. And you're ignoring the return value. It should be
int count = write(client_socket_filedescriptor, message, strlen(message));
if (count == -1)
perror("write"); // or better
char* message = "<query>\n";
read(socket_filedescriptor, buffer, sizeof(buffer));
That should be
int count = read(socket_filedescriptor, buffer, sizeof(buffer));
if (count == -1)
perror("read"); // or better
else if (count == 0)
; // end of stream: the peer has disconnected: close the socket and stop reading
else
Back to your code:
printf("%s", buffer);
That should be
printf("%.*s", count, buffer);
I plan to use strcmp()
You should plan to use strncmp(), with count above as the length parameter. In any case you can't assume the input ends with a null unless you (a) ensure you send the null, which you aren't, and (b) write a read loop that stops when you've read it.
I have the following code in server.c
while (1) {
char msg[1024];
recv(fd, msg, 1024, 0);
}
From client, first, I sent "hello world".
And then I received "hello world" in server.
I then sent "hexx" to server.
But I received "hexxo world" on server.
It seems as if msg wasn't cleared fully.
Please let me know what I'm doing wrong.
Cheers.
You are allocating 1024 bytes for message and never zeroing that data. You are just reading into the same buffer over and over. First pass it reads "hello world" in the second pass you are putting "hexx" in the same starting address resulting in "hexxo world"
As DoxyLover mentions you can null terminate the newly read string and get what you are looking for.
tcp recv not clearing old data
Who said it would? Not that it should be necessary. You're ignoring the count returned by recv(). After calling recv(), there are three possibilities:
Return value of -1: an error; call perror().
Return value of 0: end of stream: close the socket and exit the read loop.
Return value is positive: you have received exactly that many bytes into your buffer, and you should not assume that any data beyond that count is valid.
At present you're doing none of these things correctly.
read() does not null terminate the buffer. Therefore, you are seeing the old data left over in the buffer.
What you want is something like:
while (1) {
char msg[1024];
ssize_t n = recv(fd, msg, 1023, 0);
if (n >= 0)
msg[n] = '\0';
}
Note that I am limiting the read to one less than the size of the buffer to allow space for the null byte. Obviously, this only works with text data. With binary data, you need to record the return value from read() and use that as a byte count when processing the buffer. For example, to copy data from one socket to another:
while (1) {
char msg[1024];
ssize_t n = recv(fd, msg, 1024, 0);
if (n > 0)
send(second_fd, msg, n, 0);
}
All of this is very simplified - you need error checking, check the return from read() to make sure any bytes were received, check the return from send() to make sure all of the byte were sent, etc.
Am back with C sockets question.
I am trying to receive a char array from a client via TCP. I have the following recv code:
char buffer[2048];
int recvBytes = 0;
while (1) {
if ((clntSockfd = accept(servSockfd, (struct sockaddr *) &clntAddr, &clntSockAddrLen)) == -1) {
printf("Unable to accept client connection\n");
exit(1);
}
else {
printf("Client connection accepted!\n");
}
/* clear buffer */
memset(buffer, 0, sizeof(buffer));
recvBytes = recv (clntSockfd, buffer, sizeof(buffer), 0);
printf("Bytes received: %i\n", recvBytes);
printf("Char array received: %s\n", buffer);
}
I noted that upon execution, recvBytes shows zero in the first iteration. It's only after the second iteration that it picks up the incoming char array.
I would like to find out will recv block until I receive data from the incoming socket? How should I discard the unwanted chars in the buffer - i.e. drop the chars received from the first iteration.
Many thanks!
-- edit ---
Hi all, I have appended the console output from eclipse.
**... <- initialization stuff
Binding socket to port
Socket binded
Start listening on port 8081.
Client connection accepted! *while loop - first iteration
Bytes received: 0 *while loop - first iteration
Char array received: *while loop - first iteration
Client connection accepted! *while loop - second iteration
Bytes received: 22 *while loop - second iteration
Char array received: 1~Message~HowAreYou? *while loop - second iteration**
Hope the above console output illustrates my questions clearer, regarding the first and second iterations. From the above, the first iteration is not receiving any bytes but recv does not block. I thought recv was supposed to block until it receives bytes?
I believe the recv only returns 0 if the remote end closes the connection (for stream sockets such as TCP) or if a packet with no payload is received (datagram sockets such as UDP).
If the socket has been set to non-blocking mode (default is blocking), and there's no data yet, you'd get an error code, either EAGAIN or EWOULDBLOCK depending on the OS.
In any case, each time recv returns, the new data will be stored at the beginning of the buffer. It won't append to previously received data unless you calculate a pointer designed to store new data after the old.
If your socket is a blocking socket, then recv function will block till you get some data. recv function will return 0 only when the other side closes the connection on most systems.
I suggest you recheck your code and execution and let us know the exact output.
Refer here and here for more details.
If you know what to expect of the data that you receive you can drop the first set of characters. For example if you know what will the length of the packet be or the source of the message or the header information then you can validate and ignore the first set of characters.