I got a problem on Linux socket programming, and I can`t understand the situation.
It's a simple echo server-client program pair.
This is what I programmed:
This is the echoClient.
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#define RCV_BUF_SIZE 512 //receive buffer size
int main(int argc, char *argv[])
{
int sock; //socket
struct sockaddr_in echoServAddr;//server socket address struct
unsigned short echoServPort; //server port
char *servIP; //server address
char *echoString; //sending msg
char echoBuffer[RCV_BUF_SIZE]; //receive buffer
unsigned int echoStringLen = 0; //msg length
int bytesRcvd, totalBytesRcvd; //received bytes, total bytes received
if((argc < 2) || (argc > 3)) //if there are no right arguements, throw error and exit program
{
printf("Usage : %s <Server IP> [<Echo Port>]\n", argv[0]);
exit(1);
}
servIP = argv[1];
if(argc == 3)//user defined exact port
{
echoServPort = atoi(argv[2]);
}
else//user didnt defined, use well-known port
{
echoServPort = 7;
}
if((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)//if socket creation failed
{
printf("socket() failed\n");
exit(1);
}
memset(&echoServAddr, 0, sizeof(echoServAddr));//memory reset
echoServAddr.sin_family = AF_INET; //setting server's address
echoServAddr.sin_addr.s_addr = inet_addr(servIP);
echoServAddr.sin_port = htons(echoServPort);
if(connect(sock, (struct sockaddr*)&echoServAddr, sizeof(echoServAddr)) < 0)//connect try, -1 if failed
{
printf("connect() failed\n");
perror("error is : ");
exit(1);
}
printf("to exit, type \"/exit\"\n");
while(1)
{
printf("insert echo word : ");
echoString = gets();
echoStringLen = strlen(echoString);
if(echoStringLen > 512)//msg's length
{
printf("echo word is too long! (must be shorter than 512)\n");
echoStringLen = 0;
continue;
}
if(!strcmp(echoString, "\/exit"))
{
if(send(sock, echoString, echoStringLen, 0) != echoStringLen)//send to server, if sended bytes are smaller than string length
{
printf("sending close socket failed\n");
exit(1);
}
printf("clossing socket...\n");
break;
}
if(send(sock, echoString, echoStringLen, 0) != echoStringLen)//send to server, if sended bytes are smaller than string length
{
printf("send() failed\n");
exit(1);
}
totalBytesRcvd = 0;
while(totalBytesRcvd < echoStringLen)//while received bytes are shorter than msg's length
{
if((bytesRcvd = recv(sock, echoBuffer, RCV_BUF_SIZE-1, 0)) <= 0)//-1 for null char
{
printf("recv() failed");
exit(1);
}
totalBytesRcvd += bytesRcvd; //++ total bytes received
echoBuffer[bytesRcvd] = '\0'; //set last char to null cahr
printf(echoBuffer); //print received buffer
}
printf("\n");
}
close(sock);
exit(0);
}
and, this is the echoServer.
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <stdlib.h>
#define RCV_BUF_SIZE 512 //receive buffer size
#define MAX_BACKLOG 5
int main(int argc, char *argv[])
{
struct sockaddr_in echoServAddr, echoClntAddr; //define socket address(server, client)
int servSock, clntSock; //socket
unsigned short echoServPort; //port
unsigned int clntLen; //client address length
char echoBuffer[RCV_BUF_SIZE]; //receive buffer
int recvMsgSize; //received msg size
printf("echooo!\n\n");
echoServPort = atoi(argv[1]);
if((servSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) //socket creation failed
{
printf("socket() failed\n");
exit(1);
}
if(argc != 2) //if there are no right arguements, throw error and end program
{
printf("Usage : %s port\n", argv[0]);
exit(1);
}
memset(&echoServAddr, 0, sizeof(echoServAddr)); //memory reset
echoServAddr.sin_family = AF_INET; //define server address type
echoServAddr.sin_addr.s_addr = htonl(INADDR_ANY);
echoServAddr.sin_port = htons(echoServPort);
if(bind(servSock, (struct sockaddr *)&echoServAddr, sizeof(echoServAddr))<0)//bind try, return -1 if error
{
printf("bind() failed, socket number : %d\n", servSock);
perror("Error : ");
exit(1);
}
if(listen(servSock, MAX_BACKLOG) < 0)//listen try, return -1 if error
{
printf("listen(failed\n");
exit(1);
}
while(1)
{
clntLen = sizeof(echoClntAddr);
if((clntSock = accept(servSock, (struct sockaddr*)&echoClntAddr, &clntLen))<0)//accept try, return -1 if error
{
printf("recv() failed\n");
exit(1);
}
while(1)
{
if((recvMsgSize = recv(clntSock, echoBuffer, RCV_BUF_SIZE, 0)) < 0)//recv try, return -1 if error
{
printf("recv() failed\n");
exit(1);
}
if(!strcmp(echoBuffer, "\/exit"))
{
break;
}
if(send(clntSock, echoBuffer, recvMsgSize, 0) != recvMsgSize)//send try, if sended bytes are shorter than recved bytes: throw error
{
printf("send() failed\n");
exit(1);
}
}
}
close(clntSock);
}
Here's the simple description.
server starts and keep listening.
client connects.
client gets echo word from user, and send them to server.
server receives, and return them.
repeat, but once user enters "/exit", client sends "/exit", and closes socket.
and server receives "/exit", server closes socket and exits.
But, here's the problem. The server is ok with sending echo word to client, but the server process 'sometimes' terminates without any sign when client sends "/exit". I don`t know why, but not always.
I tried to put perror()
at end of the inner while loop, or outer while loop, but I can`t figure it out.
I would be very happy if someone help me out with this server problem.