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.
Related
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 need bit clarification on using multiple send/recv in socket programs.
My client program looks below(Using TCP SOCK_STREAM).
send(sockfd,"Messgfromlient",15,0);
send(sockfd,"cli1",5,0);
send(sockfd,"cli2",5,0);
send(sockfd,"cli3",5,0);
send(sockfd,"cli4",5,0);
send(sockfd,"cli5",5,0);
and the server program looks like below.
recv(newsockfd,buf,20,0);
printf("Buffer is %s\n",buf);
when i execute the above program, the output is as below:
Client Msg :Messgfromlient
I believe that the buf size is 20, so only one buffer is getting received.
Adding one more recv on server side.
char buf[20],buf[20];
------skipped------
recv(newsockfd,buf,20,0);
recv(newsockfd,buf1,20,0);
printf("Client Msg :%s\n",buf);
printf("Client Msg :%s \n",buf1);
output:
1st trial:
Client Msg :Messgfromlient
Client Msg :cli2
2nd trail:
Client Msg :Messgfromlient
Client Msg :cli1
As we can see that there is some contradiction in the ouputs,
From client side it looks all the msgs are getting sent, but in server, msg will be received based on buf size,here eventhough buf1 has size of 20, why 'cli3''cli4''cli4' msgs are not getting received on buf1?. Is there any specific limit is there? Please clarify on this.
Thanks in Advance,
Raja
TCP is a byte stream based protocol, it knows nothing about messages. You send 25 bytes in total, and each recv on the other side will read some of those bytes. You can get 20, you might get 1 and then 19 in the next read, you might get 5 then 4 then 11 then 5. The size parameter to recv is the maximum number to read.
You need to loop until you read the whole message yourself, and also understand you might receive more than one "send" in the same received message.
the server program looks like below.
recv(newsockfd,buf,20,0);
printf("Buffer is %s\n",buf);
This is already wrong. It should be:
int count = recv(newsockfd,buf,20,0);
if (count == -1)
{
perror("recv"); // please improve this message
close(newsocketfd);
}
else if (count == 0)
{
// peer has closed the connection
close(newsockfd);
}
else
{
printf("Buffer is %.*s\n",count,buf);
}
This should give you enough of a hint ...
You've got 2 issues:
When you're displaying the results, you're going to stop at the first null byte, which is always after "Messgfromlient". There may be more text already received, but you're not displaying it.
The second issue is that the TCP connection is a stream. You may receive all the data in one go, you may receive only the first byte. You don't know which one is it and can't predict it. You need to handle incomplete reads in your application and you have to handle retries.
You can however make it more likely that all the data will be sent in one packet rather than 6. Have a look at the TCP_CORK option.
I am working on an program for school and having some issues with sockets. I have pasted the write and read commands from my program below since I think these are the problem. The program should take the plaintext file and encrypt it using the key provided.
MY PROBLEM: When I execute the program using "client [plaintext] [key] [port]" the program returns "Reading data from client -- 140 bytes" and then just hangs. I can hit ctrl-c and the program prints the correct output for ptext and ktext and that 37 bytes were sent back to the client (which is the correct number of bytes). I feel like the encrypted text should print as well but it does not.
TWO QUESTIONS:
1) Why does the program hang?
2) Why does it seem like data is written from the server to the client but the client does not read any of the data?
Thank you in advance for any help you can offer.
CLIENT
n = write(sockfd,ptext,strlen(ptext));
bzero(crypt_text, BUF_MAX);
bzero(buffer, BUF_MAX);
while((n = read(sockfd,buffer,BUF_MAX))>0){
printf("Reading data from Server -- %d bytes\n",n);
strcat(crypt_text, buffer);
bzero(buffer,BUF_MAX);
}
if (n < 0){
error("ERROR reading from socket");
}
printf("%s", crypt_text);
SERVER
while((n = read(newsockfd,buffer,512))>0){
printf("Reading data from client -- %d bytes\n",n);
strcat(full_text, buffer);
bzero(buffer,BUF_MAX);
}
if (n < 0){
error("ERROR reading from socket");
}
bzero (ptext,BUF_MAX);
bzero (ktext, BUF_MAX);
strcpy(ptext, strtok(full_text,"["));
strcpy(ktext, strtok(NULL, "["));
printf("ptext length ==%s %d\n\n",ptext,strlen(ptext)); //Prints the correct plain text
printf("ktext length ==%s %d\n\n",ktext,strlen(ktext)); //prints the correct key
crypt_text = encrypt(ptext, ktext);
n = write(newsockfd,crypt_text,strlen(crypt_text));
printf("WRITE TO CILENT ==== %d",n); //This returns the correct number of bytes that should be sent back to client
if (n < 0){
error("ERROR writing to socket");
}
As is, your client and server will always hang waiting for each other. This is because read() blocks by default until new data is available to fetch from the file (in this case, a socket).
Look carefully at the code:
The client writes once into the socket before entering the read loop
The server only reads from the socket (well, further down there is a write(), but it will never reach it). The first time the loop runs on the server, it will read the data that the client initially wrote into the socket.
The server processes the data it just read and concatenates it to full_text. Then it goes back to the loop condition, where it calls read() again. read() blocks because there is nothing else to read from the socket at this point.
The client enters a similar loop where it attempts to read from the socket, expecting messages from the server.
At this point, both the server and the client are blocked waiting for messages from each other, which will never happen.
Tu put it another way: you only wrote to the socket once, and somehow you expect to read it multiple times.
You have to rethink your design. Go back to the problem description, work your way through a simple protocol, dry run it on paper, and then implement it - that's how it's done in the real world :)
There are other bugs in your code. For example you write this:
strcat(full_text, buffer);
But buffer is not NUL terminated. n bytes have been read, the rest of the buffer is indeterminate. You should set a '\0' byte at offset n and only try reading BUF_MAX-1 bytes to keep a byte available for all cases and do this:
buffer[n] = '\0';
strcat(full_text, buffer);
Furthermore, you do not test if there is enough room available in full_text for the n+1 bytes strcat will copy at the end.
On another front, packets can be sliced and diced into chunked of different sizes when received by the server. Buffering is required to ensure a reliable client / server communication. To enable this buffering, you need to devise a protocol to determine when a packet has been fully received: a simple protocol is to transmit lines terminated by '\n'.
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..