Select system call not scanning more than 2 descriptors - c

I am writing a Server program serving to Multiple client(max 5). As any client connects to server, server stores the descriptor into an array and checks for any activity in those descriptors via Select system call. But, it is only reading from any 2 clients only and rest client requests are not being served at all. Here is a code for Server
#define NUM_CLIENT 5
void main(int argc,char** argv)
{
int master_sock, newSocket, err;
struct sockaddr_in Server_addr, Client_addr;
char buf[100];
int i=0;
int activity;
//socket descriptors for select
fd_set readfd;
int client_fd[NUM_CLIENT]={-1,-1,-1,-1,-1};
//Socket creation
master_sock= socket(AF_INET,SOCK_STREAM,0);
if(master_sock<0){
perror("socket");
return;
}
//structure filling for listening to the port
Server_addr.sin_family = AF_INET;
Server_addr.sin_port = htons(atoi(argv[1]));
Server_addr.sin_addr.s_addr = INADDR_ANY;
//Binding to the Address and port filled in structure
err = bind(master_sock,(struct sockaddr*)&Server_addr,sizeof(Server_addr));
if(err<0){
perror("socket");
return;
}
printf("\nlistening to port");
err = listen(master_sock,NUM_CLIENT); //to inform, the willlingness to accept connections.
if(err<0){
perror("Listen");
return;
}
printf("\nAccepting connection");
while(1)
{
//Select modifies the objects in structure for any activity,
// So we need to load them again.
FD_ZERO(&readfd); //clearing the readfd list
FD_SET(master_sock,&readfd); //adding the descriptor for select to listen
for(i=0;i<NUM_CLIENT;i++){
if(client_fd[i] != -1){
FD_SET(client_fd[i],&readfd); //Add socket to the list
}
}
//Descriptors loaded..
//start Select operation....
activity = select(NUM_CLIENT+1,&readfd,NULL,NULL,NULL); //wait here until any activiy occurs
if(activity < 0){
perror("Select");break;
}
printf("\nactivity happened in socket...");
//If activity related to master socket i.e. New client is trying to connect.
if( FD_ISSET(master_sock,&readfd) ) {
printf("\nactivity in master socket...");
int len = sizeof(Client_addr);
//Accept the connection
newSocket = accept(master_sock, (struct sockaddr*)&Client_addr ,&len); //blocking call
if(newSocket<0){
perror("accept");return;
}
printf("\nNew connection accepted");
// puts("Receiving data");
if( recv(newSocket,buf,100,0) > 0 ) //blocking call
printf("\n%s",buf);
else
strcpy(buf,"hey");
// puts("Sending data");
if( send(newSocket,buf,strlen(buf),0) < 0 )
perror("send");
//creating client database of descriptors
for(i=0;i<NUM_CLIENT;i++){
printf("\nfd[%d] = %d\n",i,client_fd[i]);
if(client_fd[i] == -1){
client_fd[i]= newSocket;
//FD_SET(newSocket,&readfd); //Add socket to the list
//printf("\nfd[%d] = %d\n",i,client_fd[i]);
break;
}
}
}
//If activity(read or write) in other sockets, check it out
printf("\nChecking Activity in Other File Descriptors\n");
for(i=0;i<NUM_CLIENT;i++){
if(FD_ISSET(client_fd[i],&readfd)){
printf("\nactivity in client %d ...",i);
// puts("Receiving data");
if( recv(client_fd[i],buf,100,0) > 0 ) //blocking call
puts(buf);
else
strcpy(buf,"hello");
// puts("Sending data");
if( send(client_fd[i],buf,strlen(buf)+1,0) == -1 )
perror("send");
//printf("\n%s",buf);
}
}
}
}
And every client sends and receive data after sleeping for given time(provided via command line). Example: client1 5sec ,client2 4sec and so on...
The code for client is :
void main(int argc, char** argv)
{
int fd, err;
char buf[100],buf2[100];
struct sockaddr_in server;
fd = socket(AF_INET,SOCK_STREAM,0);
if(fd<0){
perror("socket");return;
}
I2A(buf,getpid()); //Integer to array conversion, returns array
strcat(buf,"Hello");
printf("%s\n",buf);
server.sin_family = AF_INET;
server.sin_port = htons(atoi(argv[1])); //Host to network
server.sin_addr.s_addr = inet_addr("127.0.0.1");
printf("Connecting with server\n");
if( connect(fd, (struct sockaddr*)&server,sizeof(server) ) < 0) {
perror("connect");return;
}
printf("Connected with server\n");
while(1){
// printf("Sending data\n");
if( send(fd,buf,20,0) < 0)
perror("send");
// printf("Receiving data\n");
if( recv(fd,buf2,sizeof(buf2),0) >0 )
printf("%s\n",buf2);
sleep(atoi(argv[2]));
}
Thanks in advance.

This line is wrong:
activity = select(NUM_CLIENT+1,&readfd,NULL,NULL,NULL); //wait here until any activiy occurs
The first argument to select() should not be NUM_CLIENT+1, but rather the maximum file descriptor value (across all of the file descriptor values that you called FD_SET() on)), plus one.

Related

Bad Address when reading from sockets in C

i'm facing a problem that i m not able to debug (it seems), let me explain the situation. I have a server that do something and 10 clients to connect. To test the code i use the same machine to host and connect the server and clients. Now, it seems that sometimes i m able to connect a random number of clients, like 4 and during the fifth connection the client side, after a good connection with the server, when i try to read from socket it gives me Bad address.
Now this number seems pretty casual, infact this error on the client side is given sometimes during the third connection, sometimes during the sixth connection and rarely never when i try to connect 10 clients. anyway most of the time this error occurs during the fifth connection.
Here the codes of server and client
Client:
void contact_server(int sockfd, int buffer_size, int reading_pipe, int writing_pipe) {
float* buff = (float*)calloc(buffer_size,sizeof(float));
int ret = 0;
while(1){
ret = 0;
while(ret == 0){
if(sizeof(float)*buffer_size <= sizeof(float)*2048){
ret = read(sockfd, buff, sizeof(float)*buffer_size);
if(ret == -1){
printf("(from server) Error description is: %s\n",strerror(errno));
exit(0);
}
}
else{
long long unsigned int sum = 0;
ret = read(sockfd, buff, sizeof(float)*2048);
if(ret == -1){
printf("(from server) Error description is : %s\n",strerror(errno));
exit(0);
}
sum+=ret;
int count;
for(count = 2048; sum < sizeof(float)*buffer_size; count+=2048, sum+=ret){
if(buffer_size-count < 2048){
ret = read(sockfd, &buff[count], sizeof(float)*(buffer_size-count));
if(ret == -1){
printf("(from server) Error description is : %s\n",strerror(errno));
exit(0);
}
}
else{
ret = read(sockfd, &buff[count], sizeof(float)*2048);
if(ret == -1){
printf("(from server) Error description is : %s\n",strerror(errno));
exit(0);
}
}
}
}
}// waiting for server
ret = write(writing_pipe,buff, sizeof(float)*buffer_size);// writing to parent process
if(ret == -1){
printf("(to parent) Error description is : %s\n",strerror(errno));
exit(0);
}
ret = 0;
while(ret == 0){
ret = read(reading_pipe, buff, sizeof(float)*buffer_size);
if(ret == -1){
printf("(from parent) Error description is : %s\n",strerror(errno));
exit(0);
}
}// waiting for parent process
ret = write(sockfd,buff, sizeof(float)*buffer_size);// writing to server
if(ret == -1){
printf("(to server) Error description is : %s\n",strerror(errno));
exit(0);
}
}
free(buff);
}
/* See server.c for more specific details
*
*
* Inputs:
*
* # int port:= the port of the server
* # char* server_address:= the server address
* # int buffer_size:= the buffer size written by the server and parent process
* # int reading_pipe:= to read from parent
* # int writing_pipe:= to write to parent
* */
int run_client(int port, char* server_address, int buffer_size, int reading_pipe, int writing_pipe){
int sockfd, connfd;
struct sockaddr_in servaddr, cli;
int sockaddr_len = sizeof(struct sockaddr_in);
// socket create and varification
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {
fprintf(stderr,"Error: socket creation failed...\n");
exit(1);
}
else
printf("Socket successfully created..\n");
bzero(&servaddr, sizeof(servaddr));
// assign IP, PORT
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = inet_addr(server_address);
servaddr.sin_port = htons(port);
// connect the client socket to server socket
if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) != 0) {
printf("connection with the server failed...\n");
exit(0);
}
else
printf("connected to the server..\n");
// function for chat
contact_server(sockfd,buffer_size,reading_pipe,writing_pipe);
// close the socket
close(sockfd);
return 0;
}
Server:
void* server_thread(void* _args) {
// depacking args
thread_args_server* args = (thread_args_server*) _args;
float* buff = (float*)calloc(args->buffer_size,sizeof(float));
int ret;
while(1){
ret = 0;
while(ret == 0){
ret = read(args->reading_pipe, buff, sizeof(float)*args->buffer_size);
if(ret == -1){
printf("Error description is : %s\n",strerror(errno));
exit(0);
}
}// waiting for parent process
ret = write(args->client_desc,buff, sizeof(float)*args->buffer_size);// writing to client
if(ret == -1){
printf("Error description is : %s\n",strerror(errno));
exit(0);
}
ret = 0;
while(ret == 0){
if(sizeof(float)*args->buffer_size <= sizeof(float)*2048){
ret = read(args->client_desc, buff, sizeof(float)*args->buffer_size);
if(ret == -1){
printf("Error description is : %s\n",strerror(errno));
exit(0);
}
}
else{
long long unsigned int sum = 0;
ret = read(args->client_desc, buff, sizeof(float)*2048);
if(ret == -1){
printf("Error description is : %s\n",strerror(errno));
exit(0);
}
sum+=ret;
long long unsigned int count;
for(count = 2048;sum < sizeof(float)*args->buffer_size; count+=2048, sum+=ret){
if(args->buffer_size-count < 2048){
ret = read(args->client_desc, buff, sizeof(float)*(args->buffer_size-count));
if(ret == -1){
printf("Error description is : %s\n",strerror(errno));
exit(0);
}
}
else{
ret = read(args->client_desc, buff, sizeof(float)*2048);
if(ret == -1){
printf("Error description is : %s\n",strerror(errno));
exit(0);
}
}
}
}
}// waiting for client
ret = write(args->writing_pipe,buff, sizeof(float)*args->buffer_size);// writing to parent process
if(ret == -1){
printf("Error description is : %s\n",strerror(errno));
exit(0);
}
}
free(buff);
return NULL;
}
/* This function creates a server on your current ip address on the port: port,
* accept a maximum number of connections = max_num_conn, and create each thread per connection.
* each thread read a float vector from a client and writes on the writing_pipes[i] this vector, then
* wait for a float vector from reading_pipe[i] and send this vector to the client.
* The ideal situation is: client -> compute some instances of the mini batch, send to server the partial derivatives
* the thread of the client on the server side read these partial derivatives, send back to the father process with writing pipes,
* the parent process sum up all these partial derivatives, update the model, send back to the thread the model updated, the thread
* send to the client and the client goes on and compute again the new partial derivatives, and so on...
*
* Inputs:
*
* # int port:= the server port
* # int max_num_conn:= the maximum number of connections accepted by the server
* # int* reading_pipes:= a pipe writing for float vector to the thread
* # int* writing_pipes:= where the thread write its vector
* # int buffer_size:= the buffer of the vector
*
* */
int run_server(int port, int max_num_conn, int* reading_pipes, int* writing_pipes, int buffer_size, char* ip){
int socket_desc, client_desc,sockaddr_len = sizeof(struct sockaddr_in),c = 1;
int ret;
struct sockaddr_in server_addr;
struct sockaddr_in* client_addr;
struct sockaddr_in* client_addr2;
bzero(&server_addr, sizeof(server_addr));
inet_pton(AF_INET, ip, &(&server_addr)->sin_addr);
// socket creation
socket_desc = socket(AF_INET,SOCK_STREAM,0);
if(socket_desc == -1){
fprintf(stderr,"Error: can't create socket\n");
exit(1);
}
// Which connection can accept
server_addr.sin_addr.s_addr = INADDR_ANY;
// Ip family
server_addr.sin_family = AF_INET;
// Port
server_addr.sin_port = htons(port);
// Handling crash case to reuse the descriptor
ret = setsockopt(socket_desc,SOL_SOCKET,SO_REUSEADDR,&c,sizeof(int));
if(ret == -1){
fprintf(stderr,"Error: setsockopt failed..\n");
exit(1);
}
// Binding newly created socket to given IP and verification
if ((bind(socket_desc, (struct sockaddr *)&server_addr, sizeof(server_addr))) != 0) {
printf("socket bind failed...\n");
exit(0);
}
else
printf("Socket successfully binded..\n");
// listen on tot number of connections
ret = listen(socket_desc,max_num_conn);
if(ret == -1){
fprintf(stderr,"Error, listen failed\n");
exit(1);
}
int i = 0;
while(1){
client_addr = calloc(1,sizeof(struct sockaddr_in));
client_desc = accept(socket_desc,(struct sockaddr*)&client_addr,(socklen_t*)&sockaddr_len);
if((client_desc == 1 && errno == EINTR)) continue;
thread_args_server* thread = (thread_args_server*)malloc(sizeof(thread_args_server));
thread->idx = i;
thread->client_desc = client_desc;
thread->client_addr = client_addr;
thread->reading_pipe = reading_pipes[i];
thread->writing_pipe = writing_pipes[i];
thread->buffer_size = buffer_size;
pthread_t t;
pthread_create(&t,NULL,server_thread,thread);
pthread_detach(t);
printf("connected client id: %d\n",i);
i++;
}
pthread_exit(NULL);
return 0;
}
The error is given by ret = read(sockfd, &buff[count], sizeof(float)*(buffer_size-count)); on client side:
Thank you for the help

client always gets connection refused when connect to server's new port socket

I'm designing a client/server system based on socket programming. Client first connects to a socket Sa with fixed port Pa on server, to get a new port number Pb for data transference. After getting Pb, close Sa and make a new socket Sb with Pb, but client always says 'connection refused'.
All above is in a child process fork() after Sa accept(), so what's the problem?
while (1)
{
struct sockaddr_in client_addr;
socklen_t length = sizeof(client_addr);
int new_server_socket = accept(server_socket,(struct sockaddr*)&client_addr,&length);
if ( new_server_socket < 0)
{
printf("Server Accept Failed!\n");
break;
}
printf("get new connection!\n");
int child_process_pid = fork();
if(child_process_pid == 0 )
{
close(server_socket);
int dataSock;
char buffer[BUFFER_SIZE];
bzero(buffer,BUFFER_SIZE);
length = recv(new_server_socket,buffer,BUFFER_SIZE,0);
if (length < 0)
{
printf("Server Recieve Data Failed!/n");
exit(1);
}
if(strcmp(buffer, "Get New Port\n") == 0)
{
srand((unsigned)time(NULL));
dataSock = (rand() % 10000) + 20000;
//printf("num is %d\n", num);
char sockNum[6];
sprintf(sockNum, "%d", dataSock);
bzero(buffer, BUFFER_SIZE);
strcpy(buffer, "The new port num is ");
strcat(buffer, sockNum);
strcat(buffer, " \n");
struct sockaddr_in data_server_addr;
bzero(&data_server_addr,sizeof(data_server_addr));
data_server_addr.sin_family = AF_INET;
data_server_addr.sin_addr.s_addr = htons(INADDR_ANY);
data_server_addr.sin_port = htons(dataSock);
int data_server_socket = socket(AF_INET,SOCK_STREAM,0);
if( data_server_socket < 0)
{
printf("Create Socket Failed!");
exit(1);
}
if( bind(data_server_socket,(struct sockaddr*)&data_server_addr,sizeof(data_server_addr)))
{
printf("Server Bind Port : %d Failed!", dataSock);
exit(1);
}
if ( listen(data_server_socket, LENGTH_OF_LISTEN_QUEUE) )
{
printf("Server Listen Failed!");
exit(1);
}
send(new_server_socket,buffer,BUFFER_SIZE,0);
close(new_server_socket);
while(1)
{
struct sockaddr_in client_addr;
socklen_t length = sizeof(client_addr);
int new_data_server_socket = accept(data_server_socket,(struct sockaddr*)&client_addr,&length);
if ( new_data_server_socket < 0)
{
printf("Server Data Connection Accept Failed!\n");
break;
}
printf("get new data connection!\n");
You shouldn't send the new port number until after the bind succeeds. And you don't need to use a randomized data port number at all. Just specify zero, do the bind(), call getsockname(), and see what port number the system allocated. Then send that to the client.

how can i display client address using c socket program?

My project is : Client receives the raw packet from the Ethernet saves it in a file called 'sniff_data.bin' and sends it to the server. Server receives the contents processes the packet( distinguishes between tcp,icmp,udp etc) and saves in a text file called 'info_agent_ report. txt' file. i think there is some mistake in my code. can anybody please guide me , help me out.
int main()
{
int sockfd, new_sockfd,log,n,x1,x2;
int server_len, client_len,len;
int cont,fh,cont2,x;
int result1;
struct sockaddr_in serveraddress;
struct sockaddr_in address;
struct sockaddr_in client_address;
FILE *ia_address;
char *fname = "/home/shishira/Desktop/packet_capture/info_agent_report.txt";
int buffsize=1024;
char buffer1[1024];
char buffer[1024];
char clntName[INET_ADDRSTRLEN];
if((sockfd = socket(AF_INET,SOCK_STREAM,0))>0)
printf("\n ---------------------------Task Agent---------------------------\n");
printf("\n Socket was created\n");
/* Name the socket. */
address.sin_family = AF_INET;
address.sin_addr.s_addr = inet_addr("127.0.0.1");
address.sin_port = htons(9734);
server_len = sizeof(address);
bind(sockfd, (struct sockaddr *)&address, server_len);
/* Create a connection queue and wait INFO_AGENT_REPORTS */
listen(sockfd, 5);
while(1)
{
char ch;
printf("\n\n Task agent waiting...\n");
/* Accept a connection to collect report from INFO_AGENT */
client_len = sizeof(client_address);
new_sockfd = accept(sockfd,(struct sockaddr *)&client_address, &client_len);
if (new_sockfd==-1) { perror("Connection Not Accepted!!"); return(1);}
else
{
// x=fork();
// if (x==0) // child process starts
// {
printf("\n Information agent is connected\n");
//for displaying the client address
if(inet_ntop(AF_INET,&client_address.sin_addr.s_addr,clntName,sizeof(clntName))!=NULL)
{
ia_address = fopen("info_agent_report.txt","a+");
fprintf(ia_address,"\nFrom InformationAgent:%s\n",clntName);
fclose(ia_address);
}
printf("\n Task agent processed the contents and saved it in 'info_agent_report'
file\n\n");
log=open("info_agent_report.txt",O_CREAT|O_RDWR|O_APPEND,0777);
if(log==-1)
{
perror("cannot open info_agent_report file\n");
return(1);
}
do
{
x1=read(new_sockfd, buffer1, 1024);
x2=write(log,buffer1,x1);
}
while (x1>0);
data_process();//for processing the packet
close(log);
// } child process ends
close(new_sockfd);
}
}
I have written the code for displaying the client address in info_agent_report.txt. but is not getting dispalyed :(
To display client name: ( put this after accept )
char clntName[INET_ADDRSTRLEN]; // String to contain client address
if (inet_ntop(AF_INET, &clntAddr.sin_addr.s_addr, clntName,sizeof(clntName)) != NULL){
printf("Handling client %s/%d\n", clntName, ntohs(clntAddr.sin_port));
}
Or this:
char clntName[INET6_ADDRSTRLEN];
char portName[6];
if(getnameinfo(&client_address,sizeof client_address,clntName,sizeof(clntName),NULL,0,NI_NUMERICHOST|NI_NUMERICSERV|NI_NUMERICSCOPE)==0){
printf("Client = %s/%s\n",clntName,portName);
} else {
printf("Unable to get address\n");
}

How can I display the client IP address on the server side?

My mini project is on implementing a c socket program where multiple clients send files to two or three servers. i have implemented these. but for handling the client request i need to create a child process is it? how can i do that . like have to handle the request separately.please anybody guide me to do it.
server:
int main()
{
int sockfd, new_sockfd,x1,x2,log,n;
int server_len, client_len,len;
int cont,fh,cont2;
int result1;
struct sockaddr_in serveraddress;
struct sockaddr_in address;
struct sockaddr_in client_address;
FILE *ia_address;
char *fname = "/home/shishira/Desktop/packet_capture/info_agent_report.txt";
int buffsize=1024;
char buffer1[1024];
char buffer[1024];
char clntName[INET_ADDRSTRLEN];
if((sockfd = socket(AF_INET,SOCK_STREAM,0))>0)
printf("\n Socket was created\n");
/* Name the socket. */
address.sin_family = AF_INET;
address.sin_addr.s_addr = inet_addr("127.0.0.1");
address.sin_port = ntohs(9734);
server_len = sizeof(address);
bind(sockfd, (struct sockaddr *)&address, server_len);
/* Create a connection queue and wait INFO_AGENT_REPORTS */
listen(sockfd, 5);
while(1)
{
char ch;
printf("\n\n Task agent waiting...\n");
/* Accept a connection to collect report from INFO_AGENT */
client_len = sizeof(client_address);
new_sockfd = accept(sockfd,(struct sockaddr *)&client_address, &client_len);
if (new_sockfd==-1) { perror("Connection Not Accepted!!"); return(1);}
else
{
printf("\n Information agent is connected\n");
if(inet_ntop(AF_INET,&client_address.sin_addr.s_addr,clntName,sizeof(clntName))!=NULL)
{
ia_address = fopen("info_agent_report.txt","a+");
fprintf(ia_address,"\nFrom InformationAgent:%s\n",clntName);
fclose(ia_address);
}
printf("\n Task agent received the contents and saved it in 'info_agent_report' file");
log=open("info_agent_report.txt",O_CREAT|O_RDWR|O_APPEND,0777);
if(log==-1)
{
perror("cannot open info_agent_report file\n");
return(1);
}
do
{
x1=read(new_sockfd, buffer1, 1024);
x2=write(log,buffer1,x1);
}
while (x1>0);
close(log);
close(new_sockfd);
}
/*this is to connect to other server */
/* connect socket to the interface server's socket. */
int interface_sockfd = socket(AF_INET,SOCK_STREAM,0);
serveraddress.sin_family = AF_INET;
serveraddress.sin_addr.s_addr = inet_addr("127.0.0.1");
serveraddress.sin_port = 9735;
len = sizeof(serveraddress);
//len=sizeof(address);
if((result1 = connect(interface_sockfd, (struct sockaddr *)&serveraddress, len))==0)
printf("\n Connecting to the Interface server\n");
if(result1 == -1)
{
perror(" Not able to connect to Interface Server!!!!\n");
}
fh = open(fname , O_RDONLY);
if(fh==-1)
{
perror(" INFO_AGENT_REPORT File is Not Opened!!\n");
return(1);
}
do
{
cont=read(fh, buffer, buffsize);
cont2=write(interface_sockfd,buffer,cont);
}
while (cont==1024);
close(fh);
printf("\n Task agent has sent 'info_agent_report' file to the Interface Server\n\n");
close(interface_sockfd);
}
}
getnameinfo() is more new-style.
You use it like
char clntName[INET6_ADDRSTRLEN];
char portName[6]; // I wonder if there is no appropriate constant...
if(getnameinfo(&client_address,sizeof client_address,clntName,sizeof(clntName),NULL,0,NI_NUMERICHOST|NI_NUMERICSERV|NI_NUMERICSCOPE)==0){
printf("Client = %s/%s\n",clntName,portName);
} else {
printf("Unable to get address\n");
}
Once you have done so, you won't have any difficulties mixing IPv4 and IPv6 calls.
Here is how : ( put this after accept ):
char clntName[INET_ADDRSTRLEN];
FILE *output;
if(inet_ntop(AF_INET,&client_address.sin_addr.s_addr,clntName,sizeof(clntName))!=NULL){
output = fopen("output.txt","a+");
fprintf(output,"%s%c%d",clntName,'/',ntohs(client_address.sin_port));
fclose(output);
} else {
printf("Unable to get address\n"); // i just fixed this to printf .. i had it as print before
}

Socket programming: recv/read issue

EDIT: the code below has been fixed to receive and send properly AND to account for the actual bytes of messages sent annd recieved (latter thanks to EJP)
I'm programming with C in Unix.
I have server and client that are supposed to exchange msgs. While client seems to send messages fine, server doesn't receive the messages the client is sending. I've tried using recv() and read() (i know they are practically the same thing but with extra flags on recv()) but I have no luck and I'm not really sure what the problem really is.
I put sleep(3) in the client code after every time it sends a message but i see that once client and server are connected, server immediately closes without waiting for the incoming messages. What am i doing wrong?
This is the client-side code:
#define SERVER_TCP_PORT 11112
#define MAX_DATA_SIZE 500
int main(int argc, char * argv[])
{
int sockfd;
char * host;
char msg[MAX_DATA_SIZE];/* = "get my msg!\n";*/
int msg_len;
struct hostent * hp;
struct sockaddr_in client_address, server_address;
printf("y halo thar\n");
// looking up from the host database
if (argc == 2)
host = argv[1];
else
exit(1);
printf("sdf\n");
hp = gethostbyname(host);
if (!hp)
exit(1);
printf("host found\n");
// setting up address and port structure information
bzero((char * ) &server_address, sizeof(server_address)); // copy zeroes into string
server_address.sin_family = AF_INET;
bcopy(hp->h_addr, (char *) &server_address.sin_addr, hp->h_length);
server_address.sin_port = htons(SERVER_TCP_PORT);
printf("set\n");
// opening up socket
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
exit(1);
printf("opened\n");
// connecting
if (connect(sockfd, (struct sockaddr *) &server_address, sizeof(server_address)) < 0)
exit(1);
printf("connected\n");
int i;
for (i = 0; i < MAX_DATA_SIZE; ++i)
{
msg[i] = '.';
}
msg[MAX_DATA_SIZE-1] = '\0';
for(i = 0; i < 11; i++)
{
// send message to connected socket
msg_len = write(sockfd, msg, MAX_DATA_SIZE);
if(msg_len < 1)
printf("notsent\n");
else
printf("%i bytes sent\n", msg_len);
// recieve messages from connected socket
msg_len = read(sockfd, msg, MAX_DATA_SIZE);
if (msg_len < 1)
printf("not recieved\n");
else
{
printf("%i bytes received\n", msg_len);
printf(msg);
printf("\n");
}
}
// close connection
close(sockfd);
printf("closed\n");
}
and this is the server side
#define SERVER_TCP_PORT 11112
#define MAX_DATA_SIZE 500
int main()
{
printf("o halo thar\n");
int sockfd, new_sockfd;
int client_addr_len;
char msg [MAX_DATA_SIZE];
int msg_len;
char got_msg [11] = "got ur msg\0";
struct sockaddr_in server_address, client_address;
// setting up address and port structure information
bzero((char * ) &server_address, sizeof(server_address)); // copy zeroes into string
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = htonl(INADDR_ANY);
server_address.sin_port = htons(SERVER_TCP_PORT);
// opening up socket
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
exit(1);
printf("socket is opened\n");
// binding
if (bind(sockfd, (struct sockaddr *) &server_address, sizeof(server_address)) < 0)
exit(1);
printf("socket is bound\n");
// listening
listen(sockfd,5);
printf("listening\n");
// block and wait for an incoming connection
client_addr_len = sizeof(client_address);
new_sockfd = accept(sockfd, (struct sockaddr *) &client_address, &client_addr_len);
if (new_sockfd < 0)
exit(1);
printf("accepted\n");
int i;
for( i = 0; i < 11; i++)
{
// recieve messages from connected socket
printf("waiting\n");
msg_len = read(new_sockfd, msg, MAX_DATA_SIZE);
if (msg_len < 1)
{
printf("no msg recieved\n");
}
else
{
printf("bytes recieved: %i\n", msg_len);
}
// send message to connected socket
msg_len = write(new_sockfd, got_msg, sizeof(got_msg));
if (msg_len < 1)
printf("not sent\n");
else
printf("%i bytes sent\n", msg_len);
}
// close connection
close(sockfd);
printf("socket closed. BYE! \n");
}
In the server code, the problem is on this line:
msg_len = read(sockfd, msg, MAX_DATA_SIZE);
You are calling read on sockfd, but you need to call read or recv on new_sockfd (the socket returned by accept()). new_sockfd is the one that's connected to the client (sockfd is used to accept further connections - eg if another client connects).
You should read from the socket returned by accept.
Try to call read on the socket returned from accept.
Receiver Side:
while(1)
{
len=read(sd,buff,sizeof(buff));
if(len==0)
{
//End of File receving.
break;
}
else
{
st=fwrite(buff,sizeof(char),len,fp);
}
}
Send Side:
while(!feof(fp))
{
len=fread(buff,sizeof(char),MW,fp);
if(len==0)
{
//EOF
st=write(cd,&d,sizeof(int));
break;
}
else
{
st=write(cd,buff,len);
}
}
is the implementation based on stream or datagram?
there are some problem with your operation flow. the server might start to read before client send anything.
since client and server are separated, you can imagine them running concurrently.
right after your server side "accept" connection request, there might be possibly some handshake overhead occurs or network delays causing server app to execute ahead in time, attempt to extract data but meet with errors (no data received yet).
you can try this out by adding sleep in server code after accept connection, where client should have enough time to send the data.
another better solution is to make data retrieval cope with empty buffer or asynchronous read.

Resources