Second recv() hangs - c

My client sends two c-strings to the server, only one is received the second recv() just hangs and I have to CTRL-C out of my program.
How can I get both messages to receive?
Here is the area I am having trouble with.
//SERVER CODE
// Retrieve plaintext from the client while connected.
while ((n = recv(client_socket, buffer_a, sizeof(buffer_a), 0)) > 0) {
buffer_a[n] = '\0';
// Retrieve the key from the client.
// PROBLEM HERE - THIS WILL DO NOTHING AND PROGRAM HANGS
if (recv(client_socket, buffer_b, sizeof(buffer_b)-1, 0) == -1) {
perror("recv key error");
}
}
//CLIENT CODE
while ((n = read(fileno(plain_text), buffer_a, sizeof(buffer_a)-1))
0)
/*Read contents of file*/
{
// Format the buffer as a c-string.
buffer_a[n] = '\0';
// Get the key.
if (read(fileno(key), buffer_b, sizeof(n)-1) == -1) {
perror("read key file error");
exit(1);
}
buffer_b[n] = '\0';
// Send plaintext to the server.
if (send(client_fd, buffer_a, n, 0) == -1) {
perror("send plaintext error");
exit(1);
}
// Send key to the server.
if (send(client_fd, buffer_b, n, 0) == -1)
{
perror("send key error");
exit(1);
}
}

Related

Server only sending one message to client

My Server is only able to send one message to the client (HELLO), the client then sends a WORD message and after the server had received the WORD message it's supposed to send a word.
For some reason the server only sends the HELLO message and upon receiving the WORD message it never sends the next message (in this case it's GREEK). I've tried so many different things but it just doesn't seem to work.
Server code (only the relevant parts) ALL CODE IS IN C
while (1) {
if ((newsockfd = accept(sockfd, (struct sockaddr *)&dest, &destlen)) == -1) {
perror("Accept call failed");
exit(-1);
}
if ((childpid = fork()) == 0) {
//close(sockfd);
talk_to_client(newsockfd);
//close(newsockfd);
}
else if (childpid > 0) {
//close(newsockfd);
}
}
}
talk_to_client()
void talk_to_client(int sockfd) {
char message[1024] = "HELLO";
char message2[1024] = "GREEK";
char recieved[1024];
ssize_t n;
//cannot send more than one!!!!!!!!! WHY NOT
write(sockfd, message, sizeof(message));
while (1) {
recv(sockfd, recieved, sizeof(recieved), 0);
if (recieved == "WORD") {
//send initial word
printf("SENDING WORD");
write(sockfd, message2, sizeof(message2));
}
if (recieved == "QUIT") {
//close connection
close(sockfd);
}
}
return;
}
Client code (only relevant parts)
char srv[512];
char cli[512] = "WORD";
// Connects socket to server
rv = connect(sockfd, (struct sockaddr *) servaddr, sizeof(struct sockaddr));
if (rv == -1){
perror("Error connecting to the server");
exit(-1);
}
if(recv(sockfd, srv, sizeof(srv), 0) == -1) {
perror("Client receiving error");
}
printf("Client received: %s\n", srv);
if(send(sockfd, cli, sizeof(cli), 0) == -1){
perror("Error sending message to the server");
exit(-1);
}
printf("Client sending: %s\n", cli);
if(recv(sockfd, srv, sizeof(srv), 0) == -1) {
perror("Client receiving error");
}
printf("Client received: %s\n", srv);
close(sockfd);
I tried many different ways to write to client (write, send, etc..) and I know for a fact it has nothing to do with my connect, bind, socket, listen or accept calls but this is the output I keep getting,
Client received: HELLO
Client sending: WORD
Client received:
char cli[512] = "WORD";
...
if(send(sockfd, cli, sizeof(cli), 0) == -1){
sizeof(cli) is 512 based on the definition of cli. So it will send 512 bytes. strlen(cli)+1 would be more correct, i.e. send the string and the \0 at the end of the string.
recv(sockfd, recieved, sizeof(recieved), 0);
This will thus likely receive these 512 bytes in the server, i.e. WORD\0 followed by many bytes junk. Note that I said "likely" since TCP is not a message based protocol but a byte stream and a single send does not need to match a single recv.
if (recieved == "WORD") {
This does not do a string comparison but compares pointer values. strcmp would be more correct here.

Closing server using select function

So, I am new to socket programming in C and am using the select function to communicate with multiple clients on a server. The server essentially just echos a buffer back to a client based on a requirest. I have used Beej's guide to network programming as the model for my server. What is not clear to me is whether I am exiting the server properly when a command is sent to exit. The code for handling the select function looks like:
for (;;)
{
read_fds = master; // Copy the master fds to the basic read...
// Check to see if any flags have been set for reading
if (select(fdmax + 1, &read_fds, NULL, NULL, NULL) == -1)
{
perror("select");
exit(4);
}
for (i = 0; i <= fdmax; i++)
{
if (FD_ISSET(i, &read_fds))
{
if (i == listener)
{ // need to add new connnection here
addrlen = sizeof remote_addr;
newfd = accept(listener, (struct sockaddr *)&remote_addr, &addrlen);
if (newfd == -1)
{
perror("accept");
}
else
{
FD_SET(newfd, &master);
if (newfd > fdmax)
{
fdmax = newfd;
}
}
} // end add new listener
else
{
/*if (i == 0)
{
printf("Input received from stdin\n");
continue;
} */
// handle data from existing client
if ((nbytes = recv(i, input_buffer, sizeof input_buffer, 0)) <= 0)
{ // Remove connection if there is a hangup...
if (nbytes == 0)
{
printf("selectserver: socket%d hung up\n", i);
}
else
{
perror("recv");
}
close(i);
FD_CLR(i, &master);
} // no bytes error or port closed - remove from fdset
else
{
if (strchr(input_buffer,'\r') == NULL){
printf("we have a problem\n");
}
if (strcmp(input_buffer, "exit")){
printf("Exit requested...\n");
close(listener);
exit(0);
}
for (j = 0; j <= fdmax; j++)
{
if (FD_ISSET(j, &master))
{
if (j != listener && j != 0)
{
if (send(j, input_buffer, nbytes, 0) == -1)
{
error_msg = strerror(errno);
printf("%s\n", error_msg);
//perror("send");
}
}
}
}
}
}
}
}
}
and the code I am specifically concerned about is
if (strcmp(input_buffer, "exit")){
printf("Exit requested...\n");
close(listener);
exit(0);
}
where listener is the file descriptor for the listening socket. Is this the correct way of exiting this loop or is there a better way to handle this?
What you are doing is correct.
The proper way to close a socket, whether it is a connected socket or a listening socket, is with close.

password authentication in Client server model in C

I am trying to authenticate client using a password and if the client enters different password he should be again asked to re-enter the password
Following is my server code:
while (1) {
printf("Expecting the pass\n");
ret = recv(sock, pass, sizeof(pass), 0);
if (ret == -1) {
perror("Error receiving message");
exit(1);
} else {
pass[strlen(pass) - 1] = '\0';
printf("Password received %s of length %d\n", pass, strlen(pass));
}
printf("Received\n");
if (strcmp("Abhishek", pass) == 0) {
printf("Password entered is correct\n");
snprintf(buffer, sizeof(buffer), "CORRECT");
break;
} else {
printf("Incorrect Password %s\n", pass);
snprintf(buffer, sizeof(buffer), "I");
}
printf("SENDING : %s\n",buffer);
ret = send(sock, buffer, strlen(buffer), 0);
if (ret == -1) {
perror("Error sending message");
exit(1);
}
}
And client side code is :
while (1) {
printf("Enter the password :");
fgets(buf, sizeof(buf), stdin);
buf[ret] = '\0';
ret = send(sockid, buf, strlen(buf), 0);
if (ret == -1) {
perror("Error sending message");
exit(1);
} else {
printf("Password sent\n");
}
memset(&buf[0], 0, sizeof(buf));
ret = recv(sockid, buf, sizeof(buf), 0);
printf("RECEIVED %s\n", buf);
if (ret == -1) {
perror("Error receiving message");
exit(1);
}
if (buf[0] != 'I') {
break;
}
}
When I execute them in different windows, I can see at server side:
Asking for password authentication
Expecting the pass
At client side:
Start the Admin Dialogue
Enter the password :
Now when I enter password in client window, it says:
Password sent
but Server is still at
Expecting the pass
Can somebody help me with that I am new to this concept
You did not provide a complete function: definitions for the arrays and various variables are missing. Are pass and buf indeed defined an arrays?
You are not sending the '\0' terminators. The message recv'd on the client side is not null terminated. strlen(pass) invokes undefined behavior. Unlikely to be the cause of your problem, but a significant bug nonetheless.
You need some kind of protocol to determine in the server and in the client when a complete message has been received. You should either use '\n' as an end of message indicator or possibly a '\0'.
Here is how you would force null termination on the server side:
printf("Expecting the pass\n");
ret = recv(sock, pass, sizeof(pass) - 1, 0);
if (ret == -1) {
perror("Error receiving message");
exit(1);
} else {
pass[ret] = '\0';
if (ret > 0 && pass[ret - 1] == '\n')
pass[--ret] = '\0';
printf("Password received %s of length %d\n", pass, ret);
}
But this is not sufficient to ensure that the full message has been received by the server, you really should recv until you get a linefeed, or some sort of protocol indicating a complete message.
On the client side, buf[ret] = '\0'; seems useless and potentially risky.

sending a file through tcp stream socket in c for windows

I'm having a really hard time figuring out how to exit the loop on the receiver side. I have a tcp stream socket connection and I'm sending what I read from a file and putting it in the buffer. The receiver end just keeps looping writing the same info over and over. I'm sure it's because i'm not decrementing nRecv so it never hits the if(nRecv == 0) statement but i can't figure out how to decrement it. I'm posting the while loop for both sender and receiver hopefully someone can point me in the right direction.
sender
/* prepare file to send */
pf = fopen("input.txt", "rb");
if(pf == NULL)
{
printf("The file you want to send was not found");
return(1);
}
else
{
while (!feof(pf))
{
nRead = fread(bufferin, sizeof(char), 256, pf);
if (nRead <= 0)
printf("ERROR reading file");
while (nRead > 0)
{
nSent = send(filesender_socket, bufferin, nRead, 0);
if (nSent < 0)
{
printf("ERROR sending from socket = %d\n", WSAGetLastError());
break;
}
if (nSent == 0)
printf("DISCONNECTED writing to socket");
//pBuf += nSent;
//nRead -= nSent;
}
}
} //end of if statement
// Close all open sockets
#ifdef WIN
//retcode = closesocket(jsender_socket);
retcode = closesocket(filesender_socket);
if (retcode < 0)
{
printf("*** ERROR - closesocket() failed \n");
exit(-1);
}
#endif
RECEIVER
//create a new socket for file transfer
filesocket = socket(AF_INET, SOCK_STREAM, 0);
if (filesocket < 0)
{
printf("*** ERROR - socket() failed \n");
exit(-1);
}
// >>> Step #2 <<<
// Fill-in my socket's address information
receiver_addr.sin_family = AF_INET; // Address family to use
receiver_addr.sin_port = htons(PORT_FILE); // Port number to use
receiver_addr.sin_addr.s_addr = htonl(INADDR_ANY); // Listen on any IP address
filebindcode = bind(filesocket, (struct sockaddr *)&receiver_addr,sizeof(receiver_addr));
if (filebindcode < 0)
{
printf("*** ERROR - file socket bind() failed \n");
exit(-1);
}
printf("receiver accepting connections\n");
//2 DEBUG LINES
printf("received a connection from: %s port %d\n",
inet_ntoa(sender_addr.sin_addr), ntohs(sender_addr.sin_port));
if (newsockfd = listen(filesocket, 2) < 0) {
printf("newsock in listen %d\n", newsockfd);
perror("listen failed");
exit(1);
}
//listen(filesocket, 2);
//while(1) //while loop for to accept files
//{
printf("\nwaiting for accept() to complete \n");
newsockfd = accept(filesocket, (struct sockaddr *) &sender_addr, &addr_len);
printf("newsock return %d", newsockfd);
if (newsockfd < 0)
{
printf("*** ERROR - accepting() failed \n");
exit(-1);
}
// start receiving file
fp = fopen("output.txt", "wb");
if (fp == NULL)
{
printf("File not found!\n");
return NULL;
}
else
{
printf("created file output.txt\n");
}
//receive file
while(1)
{
nRecv = recv(newsockfd, bufferin, 256, 0);
if (nRecv < 0)
{
printf("ERROR reading from socket = %d\n", WSAGetLastError());
break;
}
if (nRecv == 0)
break;
while (nRecv > 0)
{
printf("%s", bufferin); // debug
nWritten = fwrite(bufferin, sizeof(char), nRecv, fp);
if (nWritten <= 0)
printf("ERROR writing to file");
//nRecv -= nWritten;
}
}
printf("File Transfer complete\n\n"); //} //end of while
The return value of recv() is as follows:
>0 -- the number of bytes received
0 -- no data (async sockets only) or other socket was closed cleanly
<0 -- an error occurred.
In your sender code, you never close the socket, so your receiver waits for more data.
not sure why but now the two lines i had commented out because they weren't working now they work..
uncommented the following lines
pBuf += nSent;
nRead -= nSent;
and these on the reciver side
nRecv -= nWritten;
and it worked like a charm.
Thank you for the help.

Client prints Half Data Before Connection is Closed By Server on Socket

I have this scenario. I'm trying to use socket in C to send and receive data. Client sends some string, server manipulates it, sends it back to the client. Everything is fine but one small issue is: The client receives only the first line from server, displays it and then halts till the connection is closed by server after a time out. Although the bytes sent by server = the bytes received by client. As soon as the connection is closed, the rest of the string is displayed by the client.
I would like to know your thoughts and possible issues. Please let me know if you ahve any questions.
Protocol used: TCP
Here is the code for the server:
for (;;)
{
n=recv(s, buf, RBUFLEN-1, 0);
if (n < 0)
{
printf("Read error\n");
closesocket(s);
printf("Socket %d closed\n", s);
break;
}
else if (n==0)
{
printf("Connection closed by party on socket %d\n",s);
closesocket(s);
break;
}
else
{
printf("Received line from socket %03d : \n",s);
printf("N bytes received: %d \n",n);
// DoSomeOperationsOnTheData()
if(send(s, buffer, n, 0) != n)
printf("Write error while replying\n");
else
{
printf("Reply sent: %d bytes\n",n);
}
}
Code for client:
do
{
memset(buffer,0x0,BUFFER_SIZE); // init line
rc = read(sd, buffer, BUFFER_SIZE);
printf("\nReceived bytes: %d", rc);
if( rc > 0)
{
printf("%s",buffer);
size +=rc;
}
}while(rc>0);
printf("\n Total recieved response bytes: %d\n",size);
close(sd);
This
do
{
memset(buffer, 0, BUFFER_SIZE); // init line
rc = read(sd, buffer, BUFFER_SIZE);
printf("\nReceived bytes: %d", rc);
if( rc > 0)
{
printf("%s",buffer);
size +=rc;
}
}while(rc>0);
should be:
memset(buffer,0x0,BUFFER_SIZE); // init line
size_t size = 0;
size_t toread = BUFFER_SIZE;
do
{
ssize_t rc = read(sd, buffer+size, toread);
if (rc > 0)
{
printf("\nReceived bytes:%zd", rc);
printf("%s", buffer);
size += rc;
toread -= rc;
}
else if (rc == 0)
{
printf("The server hung up.\");
break;
}
else
{
perror("read() failed");
break;
}
} while (toread);
if (toread < BUFFERSIZE)
{
printf("Warning: Read less bytes (%zu) then expected (%d).\n", toread, BUFFERSIZE);
}
try flush data after sent.
it needs if you use socket with fdopen
FILE *fdsock = fdopen(sock, "a+");
...
fwrite(fdsock, 1, 1 "A");
fflush(fdsock);
...
fclose(fdsock);
and to finish socket, close with shutdown(sock, SD_SEND);
UPDATE
Take memset out of loop

Resources