Review code and comment c linux and networking experts [closed] - c

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
My problem statement was to create,update,delete,display record using client server program.
Here is mine code for client
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <errno.h>
/* BufferLength is 100 bytes */
#define BufferLength 150
/* Default host name of server system. Change it to your default */
/* server hostname or IP. If the user do not supply the hostname */
/* as an argument, the_server_name_or_IP will be used as default*/
#define SERVER "The_server_name_or_IP"
/* Server's port number */
#define SERVPORT 3111
#define ID_ZERO "ID CAN'T BE ZERO"
#define FILE_ERR "CAN'T OPEN FILE"
#define ID_EXIST "ID ALREADY EXIST"
#define DEL_OK "Deleted Record"
#define CREATED_RECORD "CREATED_RECORD"
#define EMP_NOT_FOUND "EMP NOT FOUND"
#define UPDATED_RECORD "UPDATED RECORD"
#define BufferLength 150
/* Pass in 1 parameter which is either the */
/* address or host name of the server, or */
/* set the server name in the #define SERVER ... */
#pragma pack(1)
struct emprec
{
int empid;
int operation;
char name[200];
};
#pragma pack(0)
typedef struct emprec emp;
char data1[100];
int main(int argc, char *argv[])
{
/* Variable and structure definitions. */
int sd, rc, length = sizeof(int);
struct sockaddr_in serveraddr;
char buffer[BufferLength];
char server[255];
char temp;
int count=0;
int totalcnt = 0;
emp temp1;
struct hostent *hostp;
unsigned char* datas = (unsigned char*)malloc(sizeof(temp1));
/* The socket() function returns a socket */
/* descriptor representing an endpoint. */
/* The statement also identifies that the */
/* INET (Internet Protocol) address family */
/* with the TCP transport (SOCK_STREAM) */
/* will be used for this socket. */
/******************************************/
/* get a socket descriptor */
if((sd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("Client-socket() error");
exit(-1);
}
else
printf("Client-socket() OK\n");
/*If the server hostname is supplied*/
if(argc > 1)
{
/*Use the supplied argument*/
strcpy(server, argv[1]);
printf("Connecting to the following %s, port %d ...\n", server, SERVPORT);
}
else
/*Use the default server name or IP*/
strcpy(server, SERVER);
memset(&serveraddr, 0x00, sizeof(struct sockaddr_in));
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(SERVPORT);
if((serveraddr.sin_addr.s_addr = inet_addr(server)) == (unsigned long)INADDR_NONE)
{
/* When passing the host name of the server as a */
/* parameter to this program, use the gethostbyname() */
/* function to retrieve the address of the host server. */
/***************************************************/
/* get host address */
hostp = gethostbyname(server);
if(hostp == (struct hostent *)NULL)
{
printf("HOST NOT FOUND --> ");
/* h_errno is usually defined */
/* in netdb.h */
printf("h_errno = %d\n",h_errno);
printf("---This is a client program---\n");
printf("Command usage: %s <server name or IP>\n", argv[0]);
close(sd);
exit(-1);
}
memcpy(&serveraddr.sin_addr, hostp->h_addr, sizeof(serveraddr.sin_addr));
}
/* After the socket descriptor is received, the */
/* connect() function is used to establish a */
/* connection to the server. */
/***********************************************/
/* connect() to server. */
if((rc = connect(sd, (struct sockaddr *)&serveraddr, sizeof(serveraddr))) < 0)
{
perror("Client-connect() error");
close(sd);
exit(-1);
}
else
printf("Connection established...\n");
/* Send string to the server using */
/* the write() function. */
/*********************************************/
/* Write() some string to the server. */
while(1)
{
printf("Enter the choice\n");
printf("1- Insert a new record into file\n");
printf("2- Update the record\n");
printf("3- Display the records\n");
printf("4- Delete the record\n");
printf("5- Close the connection with the server\n");
int choice;
scanf("%d",&choice);
switch(choice){
case 1:
//emp temp1;
temp1.operation=1;
printf("Enter the id of the record\n");
scanf("%d",&temp1.empid);
if(temp1.empid==0)
{
printf("id cannot be zero\n");
break;
}
printf("Enter name correspond to that id\n");
scanf("%s",temp1.name);
if(strlen(temp1.name)==0)
{
printf("name cannot be empty\n");
break;
}
//printf("id that is being sent is %d\n",temp1.empid);
//printf("Name sent is %s\n",temp1.name);
memset(datas,0,sizeof(temp1));
memcpy(datas,&temp1,sizeof(temp1));
rc =write(sd,datas,sizeof(temp1));
if(rc < 0)
{
perror("Client-write() error");
rc = getsockopt(sd, SOL_SOCKET, SO_ERROR, &temp, &length);
if(rc == 0)
{
//Print out the asynchronously received error.
errno = temp;
perror("SO_ERROR was");
}
close(sd);
exit(-1);
}
else
{
printf("Client-write() is OK\n");
printf("String successfully sent!\n");
printf("Waiting the %s to echo back...\n", server);
}
// }//else loop
totalcnt = 0;
// while(totalcnt < BufferLength)
// {
/* Wait for the server to echo the */
/* string by using the read() function. */
/***************************************/
/* Read data from the server. */
rc = read(sd, &buffer, 100);
if(rc < 0)
{
perror("Client-read() error");
close(sd);
exit(-1);
}
else if (rc == 0)
{
printf("Server program has issued a close()\n");
close(sd);
exit(-1);
}
else
totalcnt += rc;
// }
printf("Client-read() is OK\n");
printf("Echoed data from the following server: %s\n", buffer);
if(strcmp(buffer,CREATED_RECORD)==0){
count++;
printf("count incremented\n");
}
break;
//}//while loop
case 2: //Update the record
{
//emp temp21;
temp1.operation=2;
printf("Enter the id for which the record is to update \n");
scanf("%d",&temp1.empid);
printf("Enter name correspond to that id\n");
scanf("%s",temp1.name);
printf("id that is being sent t update is %d\n",temp1.empid);
memset(datas,0,sizeof(temp1));
memcpy(datas,&temp1,sizeof(temp1));
rc =write(sd,datas,sizeof(temp1));
if(rc < 0)
{
perror("Client-write() error");
rc = getsockopt(sd, SOL_SOCKET, SO_ERROR, &temp, &length);
if(rc == 0)
{
//Print out the asynchronously received error.
errno = temp;
perror("SO_ERROR was");
}
close(sd);
exit(-1);
}
else
{
printf("Client-write() is OK\n");
printf("String successfully sent!\n");
printf("Waiting the %s to echo back...\n", server);
}
// }//else loop
totalcnt = 0;
//while(totalcnt < BufferLength)
//{
/* Wait for the server to echo the */
/* string by using the read() function. */
/***************************************/
/* Read data from the server. */
rc = read(sd, &buffer, 25);
if(rc < 0)
{
perror("Client-read() error");
close(sd);
exit(-1);
}
else if (rc == 0)
{
printf("Server program has issued a close()\n");
close(sd);
exit(-1);
}
else
totalcnt += rc;
//}
printf("Client-read() is OK\n");
printf("Echoed data from the following server: %s\n", buffer);
break;
case 3: //display
{
//emp temp31;
printf("IN DISPLAY\n");
printf("value of count is %d\n",count);
temp1.operation=3;
memset(datas,0,sizeof(temp1));
memcpy(datas,&temp1,sizeof(temp1));
rc =write(sd,datas,sizeof(temp1));
if(rc < 0)
{
perror("Client-write() error");
rc = getsockopt(sd, SOL_SOCKET, SO_ERROR, &temp, &length);
if(rc == 0)
{
//Print out the asynchronously received error.
errno = temp;
perror("SO_ERROR was");
}
close(sd);
exit(-1);
}
else
{
printf("Client-write() is OK\n");
printf("String successfully sent!\n");
// printf("Waiting the %s to echo back...\n", server);
}
//emp temmp;
int ii =1;
while(ii<=count){
printf("value of count is %d\n",count);
rc= read(sd,&buffer,100);
memcpy(&temp1,buffer,sizeof(temp1));
printf("\nid is = %d name is = %s\n",temp1.empid,temp1.name);
ii++;
printf("value of ii is %d\n",ii);
}
printf("display loop ended\n");
//ii=0;
/*if(rc < 0)
{
perror("Server-read() error");
close(sd);
exit (-1);
}
else if(rc == 0)
{
printf("Client program has issued a close()\n");
close(sd);
exit(-1);
}
else
{
totalcnt += rc;
printf("Server-read() is OK\n");
}*/
//}
break;
}
break;
case 4:
{
emp temp41;
temp1.operation=4;
printf("Enter id to be deleted \n");
scanf("%d",&temp1.empid);
printf("enter to be deleted is %d\n",temp1.empid);
memset(datas,0,sizeof(temp1));
memcpy(datas,&temp1,sizeof(temp1));
//sleep(10);
printf("sending\n");
rc =write(sd,datas,sizeof(temp1));
printf("sent\n");
if(rc < 0)
{
perror("Client-write() error");
rc = getsockopt(sd, SOL_SOCKET, SO_ERROR, &temp, &length);
if(rc == 0)
{
//Print out the asynchronously received error.
errno = temp;
perror("SO_ERROR was");
}
close(sd);
exit(-1);
}
else
{
printf("Client-write() is OK\n");
printf("String successfully sent!\n");
printf("Waiting the %s to echo back...\n", server);
count--;
}
rc= read(sd,&buffer,100);
//FILE_ERR
printf("Message from server is %s\n",buffer);
if(strcmp(buffer,FILE_ERR)==0){
printf("Server cant open the file.... please check at the server end\n");
close(sd);
exit(0);
//count++;
//printf("count incremented\n");
}
// if(
break;
}
case 5: // Shutdown case
{
//emp temp51;
temp1.operation=5;
memset(datas,0,sizeof(temp1));
memcpy(datas,&temp1,sizeof(temp1));
//sleep(10);
printf("Closing client and asked server too to close\n");
rc =write(sd,datas,sizeof(temp1));
if(rc < 0)
{
perror("Client-write() error");
rc = getsockopt(sd, SOL_SOCKET, SO_ERROR, &temp, &length);
if(rc == 0)
{
//Print out the asynchronously received error.
errno = temp;
perror("SO_ERROR was");
}
close(sd);
exit(-1);
}
else
{
//printf("Client-write() is OK\n");
//printf("String successfully sent!\n");
//printf("Waiting the %s to echo back...\n", server);
}
close(sd);
exit(0);
break;
}
}//switch bracket
}//switch
}//while 1
}//main
Here is mine code for server
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <unistd.h>
/* BufferLength is 100 bytes */
/* Server port number */
//ALL CONSTANTS
#define SERVPORT 3111
#define ID_ZERO "ID CAN'T BE ZERO"
#define FILE_ERR "CAN'T OPEN FILE"
#define ID_EXIST "ID ALREADY EXIST"
#define DEL_OK "Deleted Record"
#define CREATED_RECORD "CREATED_RECORD"
#define EMP_NOT_FOUND "EMP NOT FOUND"
#define UPDATED_RECORD "UPDATED RECORD"
#define BufferLength 150
#pragma pack(1)
struct emprec
{
int empid;
int operation;
char name[20];
};
#pragma pack(0)
typedef struct emprec emp;
int main()
{
/* Variable and structure definitions. */
int sd, sd2, rc, length = sizeof(int);
int totalcnt = 0, on = 1,count=0;
int i=1;//use only one int
int flag1=0;//use only one flag
char temp;
char buffer[BufferLength];
char sbuf[25];
struct sockaddr_in serveraddr;
struct sockaddr_in their_addr;
FILE *fd=NULL,*fd1=NULL;
fd_set read_fd;
emp temp2,temp8,temp3;
unsigned char* sdata = (unsigned char*)malloc(sizeof(temp2));
/* The socket() function returns a socket descriptor */
/* representing an endpoint. The statement also */
/* identifies that the INET (Internet Protocol) */
/* address family with the TCP transport (SOCK_STREAM) */
/* will be used for this socket. */
/************************************************/
/* Get a socket descriptor */
if((sd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("Server-socket() error");
/* Just exit */
exit (-1);
}
else
printf("Server-socket() is OK\n");
/* The setsockopt() function is used to allow */
/* the local address to be reused when the server */
/* is restarted before the required wait time */
/* expires. */
/***********************************************/
/* Allow socket descriptor to be reusable */
if((rc = setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on))) < 0)
{
perror("Server-setsockopt() error");
close(sd);
exit (-1);
}
else
printf("Server-setsockopt() is OK\n");
/* bind to an address */
memset(&serveraddr, 0x00, sizeof(struct sockaddr_in));
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(SERVPORT);
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
/* connect to any client that used port 3005. */
if((rc = bind(sd, (struct sockaddr *)&serveraddr, sizeof(serveraddr))) < 0)
{
perror("Server-bind() error");
/* Close the socket descriptor */
close(sd);
/* and just exit */
exit(-1);
}
else
printf("Server-bind() is OK\n");
/* The listen() function allows the server to accept */
/* incoming client connections. In this example, */
/* the backlog is set to 10. This means that the */
/* system can queue up to 10 connection requests before */
/* the system starts rejecting incoming requests.*/
/*************************************************/
/* Up to 10 clients can be queued */
if((rc = listen(sd, 10)) < 0)
{
perror("Server-listen() error");
close(sd);
exit (-1);
}
else
printf("Server-Ready for client connection...\n");
/* The server will accept a connection request */
/* with this accept() function, provided the */
/* connection request does the following: */
/* - Is part of the same address family */
/* - Uses streams sockets (TCP) */
/* - Attempts to connect to the specified port */
/***********************************************/
/* accept() the incoming connection request. */
int sin_size = sizeof(struct sockaddr_in);
if((sd2 = accept(sd, (struct sockaddr *)&their_addr, &sin_size)) < 0)
{
perror("Server-accept() error");
close(sd);
exit (-1);
}
else
printf("Server-accept() is OK\n");
/*client IP*/
printf("Server-new socket, sd2 is OK...\n");
//printf("Got connection from the f***ing client: %s\n", inet_ntoa(their_addr.sin_addr));
while(1){
/* The select() function allows the process to */
/* wait for an event to occur and to wake up */
/* the process when the event occurs. In this */
/* example, the system notifies the process */
/* only when data is available to read. */
/***********************************************/
/* Wait for up to 15 seconds on */
/* select() for data to be read. */
//FD_ZERO(&read_fd);
//FD_SET(sd2, &read_fd);
//rc = select(sd2+1, &read_fd, NULL, NULL, &timeout);
//if((rc == 1) && (FD_ISSET(sd2, &read_fd)))
//{
/* Read data from the client. */
totalcnt = 0;
//while(totalcnt < BufferLength)
//{
/* When select() indicates that there is data */
/* available, use the read() function to read */
/* 100 bytes of the string that the */
/* client sent. */
/***********************************************/
/* read() from client */
rc= read(sd2,&buffer,100);
if(rc < 0)
{
perror("Server-read() error");
close(sd);
close(sd2);
exit (-1);
}
else if (rc == 0)
{
printf("Client program has issued a close()\n");
close(sd);
close(sd2);
exit(-1);
}
else
{
totalcnt += rc;
printf("Server-read() is OK\n");
}
memcpy(&temp2,buffer,sizeof(temp2));
printf("operation is %d\n",temp2.operation);
// declare it upwards
if (temp2.operation==1)//write record
{
printf("in write record\n");
printf("id is %d\n",temp2.empid);
printf("name is %s\n",temp2.name);
fd = fopen("/home/abc/Desktop/test34.txt","a+");
while(i<=count)
{
printf("value of i is %d and count is %d\n",i,count);
fread(&temp3.empid,sizeof(temp3.empid),1,fd);
fread(&temp3.name,sizeof(temp3.name),1,fd);
if(temp2.empid==temp8.empid)
{
printf("in create:: going in id checking loop\n");
flag1=1;
temp8.empid=0;
i=0;
break;
}
i++;
}
if (flag1==1)
{
memset(sbuf,0,sizeof(sbuf));
strcpy(sbuf,ID_EXIST);
printf("temp2.empname is %s\n",temp2.name);
rc = write(sd2, sbuf, sizeof(sbuf));
i=0;
flag1=0;
//break;
}
else
{
count++;
fwrite(&temp2.empid,sizeof(temp2.empid),1,fd);
fwrite(&temp2.name,20,1,fd);
fclose(fd);
sleep(1);
memset(sbuf,0,sizeof(sbuf));
strcpy(sbuf,CREATED_RECORD);
printf("Server-Echoing back to client...\n");
rc = write(sd2, sbuf, sizeof(sbuf));
if(rc <0)
{
perror("Server-write() error");
/* Get the error number. */
rc = getsockopt(sd2, SOL_SOCKET, SO_ERROR, &temp, &length);
if(rc == 0)
{
/* Print out the asynchronously */
/* received error. */
errno = temp;
perror("SO_ERROR was: ");
}
else
printf("Server-write() is OK\n");
}
}//else bracket
}
if (temp2.operation==2)//update
{
memcpy(&temp2,buffer,sizeof(temp2));
printf("in case update\n");
printf("id is %d\n",temp2.empid);
printf("name is %s\n",temp2.name);
int id,flag=0,i=1;
//emp temp4;
fd = fopen("/home/abc/Desktop/test34.txt","r+");
if(fd==NULL)
{
printf("File cannot be opened\n");
return 1;
}
id = temp2.empid;
printf("id to search is %d\n",id);
i=1;
while(i<=count)
{
fread(&temp8.empid,sizeof(temp8.empid),1,fd);
printf("Debbugging id read is %d\n",temp8.empid);
if(temp2.empid==temp8.empid)
{
int size = ftell(fd);
printf("pointer is at position %d\n",size);
printf("emp id found\n");
fseek(fd,size,SEEK_SET);
printf("data to write is %s\n",temp2.name);
fwrite(&temp2.name,20,1,fd);
memset(sbuf,0,sizeof(sbuf));
strcpy(sbuf,UPDATED_RECORD);
printf("Server-Echoing back to client...\n");
rc = write(sd2, sbuf, sizeof(sbuf));
flag=1;
break;
}
i++;
}//while inside if
if(flag!=1)
{
memset(sbuf,0,sizeof(sbuf));
strcpy(sbuf,EMP_NOT_FOUND);
printf("Server-Echoing back to client...\n");
rc = write(sd2, sbuf, sizeof(sbuf));
printf("No emp found");
flag=0;
}
fclose(fd);
}//if update
if (temp2.operation==3)//display
{
printf("In display\n");
emp temp6;
int i =1;
fd = fopen("/home/abc/Desktop/test34.txt","r+");
if(fd==NULL)
{
printf("File cannot be opened\n");
return 1;
}
while(i<=count)
{
fread(&temp6.empid,sizeof(temp6.empid),1,fd);
fread(&temp6.name,sizeof(temp6.name),1,fd);
printf("\nid is = %d name is = %s\n",temp6.empid,temp6.name);
memset(sdata,0,sizeof(temp6));
memcpy(sdata,&temp6,sizeof(temp6));
printf("temp2.empname is %s\n",temp2.name);
rc = write(sd2, sdata, sizeof(temp6));//add a check here
sleep(1);
i++;
}
fclose(fd);
}//if display
if (temp2.operation==4)//delete record - NOT YET COMPLETE
{
printf("In case 4 THAT IS DELETE \n");
int found =0,i=1;
fd = fopen("/home/abc/Desktop/test34.txt","r+");
if(fd==NULL)
{
printf("File cannot be opened\n");
memset(sbuf,0,sizeof(sbuf));
strcpy(sbuf,FILE_ERR);
printf("sbuf is %s\n",sbuf);
rc = write(sd2, sbuf, sizeof(sbuf));
return 1;
}
fd1 = fopen("/home/abc/Desktop/test335.txt","a+");
if(fd1==NULL)
{
printf("File cannot be opened\n");
memset(sbuf,0,sizeof(sbuf));
strcpy(sbuf,FILE_ERR);
printf("sbuf is %s\n",sbuf);
rc = write(sd2, sbuf, sizeof(sbuf));
return 1;
}
printf("name to search is %s\n",temp2.name);
printf("id to delete is %d\n",temp2.empid);
emp temp7,temp10;
memcpy(&temp10,buffer,sizeof(temp10));
printf("temp 10 id to delete is %d\n",temp10.empid);
while(i<=count){
fread(&temp7.empid,sizeof(temp7.empid),1,fd);
fread(&temp7.name,sizeof(temp7.name),1,fd);
if(temp2.empid==temp7.empid){
printf("A requested by name found and deleted\n");
found = 1;
count--;
}else{
fwrite(&temp7,sizeof(temp7),2,fd1);
}
if(!found)
{
printf("cannot found the record\n");
}
i++;
}
fclose(fd);
fclose(fd1);
remove("/home/abc/Desktop/test34.txt");
rename("/home/abc/Desktop/test335.txt","/home/tarun/Desktop/test34.txt");
memset(sbuf,0,sizeof(sbuf));
strcpy(sbuf,DEL_OK);
rc = write(sd2, sbuf, sizeof(sbuf));
//for debugging
fd = fopen("/home/abc/Desktop/test34.txt","r+");
if(fd==NULL)
{
printf("File cannot be opened\n");
return 1;
}
i=0;
while(i<=count)
{
fread(&temp7.empid,sizeof(temp7.empid),1,fd);
fread(&temp7.name,sizeof(temp7.name),1,fd);
printf("\nid is = %d name is = %s\n",temp7.empid,temp7.name);
i++;
}
}// if delete record
/* When the data has been sent, close() */
/* the socket descriptor that was returned */
/* from the accept() verb and close() the */
/* original socket descriptor. */
/*****************************************/
/* Close the connection to the client and */
/* close the server listening socket. */
/******************************************/
if (temp2.operation==5)//close connection
{
printf("client has asked to shutdown ... Its time to go bbye\n");
close(sd2);
close(sd);
exit(0);
return 0;
}
}
}
I have tryed to test all the cases possible.But i request if you have please review the code and comment where more checks can be added.
Also i am getting a problem in delete record after deleteing i am not able to get the exact values please tell me whats the issue

there are several logic errors in the posted code.
Here is the details of one such error:
rc= read(sd,&buffer,100);
memcpy(&temp1,buffer,sizeof(temp1));
printf("\nid is = %d name is = %s\n",temp1.empid,temp1.name);
1) read() does not append a string terminator byte
2) memcpy() is copying the full buffer[] rather than just the number of bytes read
3) printf...%s... does not stop printing until it encounters a '\0' byte.
What happens if the number of bytes read is only a few bytes
(this can happen, and often does, which is the reason to use a 'select()/read()' with the socket set to non-blocking, loop to assure getting all the required/desired bytes of input.)
only copy the actual number of read bytes 'rc' to the 'temp1' struct.
Then insert a '\0' as the next byte.
Note: the socket has not been set to 'non-blocking' so the code will 'hang' until 100 bytes are read or the socket times out.

Related

How can I stop the while?

I have A TCP Server-Client where I enter a number with the number of times that I want to send the word to the server. So I send correctly because I print the information on a loop(in client) but in the server shows infinitely because I put while(1) but if I don't use just print it one time. I don't want to send the number to the server.
If I enter the number 4 I want to print the word "hello" four times
This is the server, now it's printing infinitely obviously.
#define MAXPENDING 5 /* Maximum number of simultaneous connections */
#define BUFFSIZE 255 /* Size of message to be received */
void err_sys(char *mess) { perror(mess); exit(1); }
void handle_client(int sock) {
char buffer[BUFFSIZE];
int received = -1;
while (1) {
/* Read from socket */
read(sock, &buffer[0], BUFFSIZE);
printf("Message from client: %s\n", buffer);
/* Write to socket */
write(sock, buffer, strlen(buffer) + 1);
/* Close socket */
close(sock);
}
}
int main(int argc, char *argv[]) {
struct sockaddr_in echoserver, echoclient;
int serversock, clientsock;
int result;
/* Check input arguments */
if (argc != 2) {
fprintf(stderr, "Usage: %s <port>\n", argv[0]);
exit(1);
}
/* Create TCP socket */
serversock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (serversock < 0) {
err_sys("Error socket");
}
/* Set information for sockaddr_in structure */
memset(&echoserver, 0, sizeof(echoserver)); /* we reset memory */
echoserver.sin_family = AF_INET; /* Internet/IP */
echoserver.sin_addr.s_addr = htonl(INADDR_ANY); /* ANY address */
echoserver.sin_port = htons(atoi(argv[1])); /* server port */
/* Bind socket */
result = bind(serversock, (struct sockaddr *) &echoserver, sizeof(echoserver));
if (result < 0) {
err_sys("Error bind");
}
/* Listen socket */
result = listen(serversock, MAXPENDING);
if (result < 0) {
err_sys("Error listen");
}
while (1) {
unsigned int clientlen = sizeof(echoclient);
/* Wait for a connection from a client */
clientsock = accept(serversock, (struct sockaddr *) &echoclient, &clientlen);
if (clientsock < 0) {
err_sys("Error accept");
}
fprintf(stdout, "Client: %s\n", inet_ntoa(echoclient.sin_addr));
/* Call function to handle socket */
handle_client(clientsock);
}
}
This is the client
printf("Enter a number between 0 to 9[0 to exit]: ");
fgets(number, 100, stdin);
while(strtol(number,&pEnd,10)!=0){
while (!((strtol(number,&pEnd,10) <= 9) && (strtol(number,&pEnd,10) >= 0))) {
printf("[ERROR] The number you entered is out of range\n");
printf("Enter a number between 0 to 9[0 to exit]: ");
fgets(number, 100, stdin);
}
if(strtol(number,&pEnd,10)!=0){
printf("Enter a word: ");
fgets(buffer, 100, stdin);
for(int i=0;i<strtol(number,&pEnd,10);i++){
write(sock, buffer, strlen(buffer) + 1);
fprintf(stdout, " sent \n");
read(sock, buffer, BUFFSIZE);
fprintf(stdout, " %s ...done \n", buffer);
}
}
printf(" Enter a number between 0 to 9[0 to exit]: ");
fgets(number, 100, stdin);
}
There are multiple problems in you code:
you do not test if read() succeeds. You should break from the loop if it fails.
you unconditionally close the socket in the body of the loop: the next read will fail and return -1 immediately, you will print a bogus message and iterate at nauseam.
you call strlen() and printf() with a buffer that might not be null terminated, potentially causing undefined behavior.
Here is a modified version:
void handle_client(int sock) {
char buffer[BUFFSIZE];
int received = -1;
if (sock < 0)
return;
for (;;) {
/* Read from socket */
received = read(sock, buffer, sizeof(buffer) - 1);
if (received <= 0)
break;
buffer[received] = '\0';
printf("Message from client: %s\n", buffer);
/* Write to socket */
write(sock, buffer, received);
}
/* Close socket */
close(sock);
}
You have an infinite loop in your hands normally that is not recommended but if you need to do it then add a if statement such:
while(1){
if(clientsock < 0){/*statement that is met so that your code stops running the if */
break;
}
}

Not receiving File transfer from TCP connection

I am writing a TCP client and server protocol for a school project. The client sends a "GET \r\n" message and the server has to transfer "+OK\r\n", size of the file and the file, in case it exists in the server directory. I'm blocked in the file transfer
I tried to solve it at small steps at a time. I set up the connection, sent the request from the client and received the "OK" message from the server.
Now I opened the file in the server and tried to send it 128 bytes at a time to the client. The reading of the file works and apparently also the sending of the buffers but the client is not receiving anything...
Here's my server.c
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include "../errlib.h"
#include "../sockwrap.h"
#define BUFLEN 128 /* Buffer length */
#define TIMEOUT 15 /* TIMEOUT */
/* FUNCTION PROTOTYPES */
void service(int s);
/* GLOBAL VARIABLES */
char *prog_name;
int main(int argc, char *argv[])
{
int conn_request_skt; /* passive socket */
uint16_t lport_n, lport_h; /* port used by server (net/host ord.) */
int bklog = 2; /* listen backlog */
int s; /* connected socket */
fd_set cset; // waiting for connection
struct timeval tval; // timeout
size_t n;
socklen_t addrlen;
struct sockaddr_in saddr, caddr; /* server and client addresses */
prog_name = argv[0];
if (argc != 2) {
printf("Usage: %s <port number>\n", prog_name);
exit(1);
}
/* get server port number */
if (sscanf(argv[1], "%" SCNu16, &lport_h)!=1)
err_sys("Invalid port number");
lport_n = htons(lport_h);
/* create the socket */
printf("creating socket...\n");
s = Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
printf("done, socket number %u\n",s);
/* bind the socket to any local IP address */
bzero(&saddr, sizeof(saddr));
saddr.sin_family = AF_INET;
saddr.sin_port = lport_n;
saddr.sin_addr.s_addr = INADDR_ANY;
showAddr("Binding to address", &saddr);
Bind(s, (struct sockaddr *) &saddr, sizeof(saddr));
printf("done.\n");
/* listen */
printf ("Listening at socket %d with backlog = %d \n",s,bklog);
Listen(s, bklog);
printf("done.\n");
conn_request_skt = s;
/* main server loop */
for ( ; ; )
{
printf("waiting for connection...\n");
/* accept next connection */
FD_ZERO(&cset);
FD_SET(conn_request_skt, &cset);
tval.tv_sec = TIMEOUT;
tval.tv_usec = 0;
n = Select(FD_SETSIZE, &cset, NULL, NULL, &tval);
if ( n > 0 ){
addrlen = sizeof(struct sockaddr_in);
s = Accept(conn_request_skt, (struct sockaddr *) &caddr, &addrlen);
showAddr("Accepted connection from", &caddr);
printf("new socket: %u\n",s);
/* serve the client on socket s */
service(s);
} else {
printf("No connection request after %d seconds\n",TIMEOUT);
}
}
}
void service(int s) {
char buf[BUFLEN]; /* reception buffer */
char filename[BUFLEN];
int n;
long filesize;
uint32_t fsize;
FILE *fp;
for ( ; ; )
{
n = recv(s, buf, BUFLEN, 0);
if (n < 0) {
printf("Read error\n");
close(s);
printf("Socket %d closed\n", s);
break;
} else if (n == 0) {
printf("Connection closed by party on socket %d\n",s);
close(s);
break;
} else {
printf("Received request from socket %03d :\n", s);
sscanf(buf, "GET %s\r\n", filename);
strcpy(buf, "+OK\r\n");
printf("%s",buf);
if(writen(s, buf, strlen(buf)) != strlen(buf))
printf("Write error while sending +OK\n");
// open file
fp = fopen(filename, "r");
if( fp == NULL){
//TODO close connection
}
// calculating dim of file
fseek(fp, 0L, SEEK_END);
filesize = ftell(fp);
rewind(fp); // go back at beginning of file
fsize = htonl(filesize); // size file in network byte order
// sending file size
if(writen(s, &fsize, 4) != 4)
printf("Write error while sending file size\n");
while(fread(buf, 1, BUFLEN - 1, fp) == BUFLEN - 1){
printf("%s", buf);
if(writen(s, buf, strlen(buf)) != strlen(buf))
printf("Write error while buf\n");
}
printf("%s", buf);
printf("I am here\n");
}
}
}
While here is my client.c
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include "../errlib.h"
#include "../sockwrap.h"
#define BUFLEN 128 /* BUFFER LENGTH */
#define TIMEOUT 15 /* TIMEOUT*/
/* GLOBAL VARIABLES */
char *prog_name;
int main(int argc, char *argv[])
{
char request[BUFLEN]; /* request buffer */
char rbuf[BUFLEN]; /* reception buffer */
uint32_t taddr_n; /* server IP addr. (net/host ord) */
uint16_t tport_n, tport_h; /* server port number (net/host ord) */
int s, len;
int result;
struct sockaddr_in saddr; /* server address structure */
struct in_addr sIPaddr; /* server IP addr. structure */
fd_set cset; // variables for timeout
struct timeval tval;
size_t n;
prog_name = argv[0];
if(argc < 4)
err_sys("Wrong number of parameters!\n");
// read address from first argument
taddr_n = inet_addr(argv[1]);
if (taddr_n == INADDR_NONE)
err_sys("Invalid address");
// read port number from second argument
if (sscanf(argv[2], "%" SCNu16, &tport_h)!=1)
err_sys("Invalid port number");
tport_n = htons(tport_h);
/* create the socket */
printf("Creating socket\n");
s = Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
printf("done. Socket fd number: %d\n",s);
/* prepare address structure */
bzero(&saddr, sizeof(saddr));
saddr.sin_family = AF_INET;
saddr.sin_port = tport_n;
saddr.sin_addr = sIPaddr;
printf("trying to connect to the server...\n");
/* connect */
showAddr("Connecting to target address", &saddr);
Connect(s, (struct sockaddr *) &saddr, sizeof(saddr));
printf("done.\n");
// loop to request files
for (int i = 3 ; i < argc ; i++ ){ // i = 4 because the first file is the fourth argument
// check if file name is too big
if(strlen(argv[i]) >= BUFLEN - 6)
err_sys("The file name is too big for the buffer request!\n");
// create the string of bytes for the request
strcpy(request, "GET ");
strcat(request, argv[i]);
strcat(request, "\r\n");
len = strlen(request);
if(writen(s, request, len) != len){
printf("Write error\n");
break;
}
printf("waiting for response...\n");
// receive file from server
n = recv(s, rbuf, BUFLEN, 0);
if (n < 0) {
printf("Read error\n");
close(s);
printf("Socket %d closed\n", s);
break;
} else if (n == 0) {
printf("Connection closed by party on socket %d\n",s);
close(s);
break;
} else {
printf("Received reply from server\n");
uint32_t fsize;
printf("%s",rbuf);
if(strcmp(rbuf, "+OK\r\n") == 0){
n = recv(s, &fsize, 4, 0);
if (n < 0) {
printf("Read error\n");
close(s);
printf("Socket %d closed\n", s);
break;
} else if (n == 0) {
printf("Connection closed by party on socket %d\n",s);
close(s);
break;
} else {
// received file dimension
fsize = ntohl(fsize);
}
while(fsize > 0){
printf("I am here1n\n");
// receive file
n = recv(s, rbuf, BUFLEN-1, 0);
if (n < 0) {
printf("Read error\n");
close(s);
printf("Socket %d closed\n", s);
break;
} else if (n == 0) {
printf("Connection closed by party on socket %d\n",s);
close(s);
break;
} else {
printf("I am here");
fsize -= n;
}
}
}
}
}
printf("===========================================================\n");
close(s);
exit(0);
}
The recv in the client where I am supposed to receive the file just blocks without receiving anything. I don't understand what I am missing...
The issue here is a common one: You're not being careful with message boundaries.
In your client, you do a recv and check whether the number of bytes is greater than 0. But then you don't do more length checking. You next do a strcmp on a particular string you're expecting to receive (+OK\r\n). But you might have received 3 bytes (+OK) or you might have received 10: (+OK\r\nXXXXX) or more [aside: also, recv doesn't guarantee your byte string is null-terminated]. There is nothing stopping the kernel on the far side from batching the preamble plus subsequent bytes into a single TCP packet. Likewise, there is nothing preventing the local side from aggregating multiple TCP packets into a single buffer.
You must provide message boundaries. If you're expecting your next message to be 5 bytes, then you should receive exactly 5 bytes (and retry if you get fewer -- being careful to check for EOF too in case the other side aborted early). Or, alternatively stick a buffering layer in front of your receive logic so that it will receive up to some large amount, return to you the number of bytes you want, and then save whatever is in excess for a subsequent "receive" call.
To restate this in a different way: Your server sends +OK\r\n, then it sends a four-byte length, then it starts sending the file. But that means your first recv on the client side could be receiving the preamble, plus the length, plus the first N bytes of the file all in one system call.
TCP does not respect, provide or enforce message boundaries.

Communication: Sending a message from a client to a server

My Server can handle multiple clients/switches at a time.
My problem is in my switch I believe, I'm trying to send an open message to the the controller. I create the the tcp socket in the switch and then right after I try to send the message to the controller, however when I try to do this, the socket disconnects from the controller and goes into an infinite loop. I'm not sure why this occurs as I'm creating and sending the message outside of my while loop. If I comment where I send the message, the socket stays connected to the controller and I am able to wait for one of a set of file descriptors to become ready to perform I/O, currently I only have the keyboard and the socket. My socket also receives a message from the controller when it's connected "You are connected to the server". In addition since my switch socket disconnects my recv() return error code 107 due to the fact the socket is disconnected.
I'm not sure If I provided too much code to look through but I added comments where I thought my error was occurring in the switch as well as the controller. Greatly appreciated for some help. I didn't add any of my own header files because they are not necessary.
This where I execute the switch. Sends and receive messages here.
#include "switch.h"
#include "openFIFO.h"
#include "packets.h"
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/select.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include<poll.h>
#include <signal.h>
void do_switch(int swIport, char *trafficfile,int swJport, int swKport, int IPlow, int IPhigh,char serverAddress[256], unsigned short portNumber){
int switch_sock;
char server_response[256];
struct pollfd pfds[6];
int rval;
/* Switch */
Switch sw;
sw.swJport = swJport;
sw.swIport = swIport;
sw.swKport = swKport;
sw.IPlow = IPlow;
sw.IPhigh = IPhigh;
int switchLength = sizeof(Switch);
// printf("\n\nstruct switchLength: %d\n", switchLength);
// printf("\n\nSwitch Struct: swIport: %d, swJport: %d, swKport: %d,
IPlow: %d, IPhigh: %d\n", sw.swIport, sw.swJport, sw.swKport, sw.IPlow,
sw.IPhigh);
printf("\n\nSwitch created with the following: swIport: %d, trafficfile:
%s, swJport: %d, swKport: %d, IPlow: %d, IPhigh: %d, serverAddress: %s,
portNumber: %d\n", swIport, trafficfile, swJport, swKport, IPlow, IPhigh,
serverAddress, portNumber);
int fifoWrite[2];
int fifoRead[2];
int counter = 0;
char message[20] = "Hello";
/* Create fifos */
if(swJport != -1){
fifoWrite[0] = openWF(swIport,swJport);
fifoRead[0] = openReadFifo(swJport, swIport);
counter = counter + 2;
}
if(swKport != -1){
fifoWrite[1] = openWF(swIport,swKport);
fifoRead[1] = openReadFifo(swKport, swIport);
counter = counter + 2;
}else if(swKport == -1){
fifoWrite[0] = openWF(swIport,swKport);
fifoRead[0] = openReadFifo(swKport, swIport);
counter = counter + 2;
}
printf("fifoWrite[0]: %d\n", fifoWrite[0]);
printf("fifoRead[0]: %d\n", fifoRead[0]);
printf("fifoWrite[1]: %d\n", fifoWrite[1]);
printf("fifoRead[1]: %d\n", fifoRead[1]);
/* Establish connection between the controller and switch */
/* Send a open packet to the controller */
/* Sending a stuct */
//PROBELM HERE BELOW!!!!!!!
switch_sock = CreateTCPClientSocket(portNumber, serverAddress);
if(send(switch_sock, message, sizeof(message), 0) == -1){
fprintf(stderr, "Send() Failed");
}
else{
printf("Open packet is being sent to the controller\n");
}
/* Initialize poll parameters */
//Keyboard
pfds[0].fd = STDIN_FILENO;
pfds[0].events = POLLIN;
// Socket!
pfds[1].fd = switch_sock;
pfds[1].events = POLLIN;
printf("Starting switch............................\n\n");
while(1){
rval = poll(pfds,2,-1);
if(rval == 0){
fprintf(stderr, "Poll timed out. \n");
}if(rval == -1){
fprintf(stderr, "ERROR: poll() failed");
exit(0);
}
/* Check Keyboard */
if(pfds[0].revents & POLLIN && pfds[0].fd == 0){
int a;
char command[1024][256];
int commands;
char buf[256];
commands = read(0, buf, 256);
buf[commands] = '\0';
buf[commands] = '\0';
char *token;
token = strtok(buf, " ");
while(token != NULL){
strcpy(command[a], token);
a++;
token = strtok(NULL, " ");
}
a = 0;
bzero(buf, 256);
if(strcmp(command[0], "list") == 0){
//TODO: Make a print function
printf("print_switch()\n");
}
if(strcmp(command[0], "exit") == 0){
//TODO: Make a print function
printf(" print_switch()\n");
printf("switch-disconnected\n");
close(switch_sock);
exit(0)
}
}
/* Server sent a welcome message */
// Might be PROBELM HERE BELOW when trying to send the initial packet to
controller!!!!!!!
if(pfds[1].revents & POLLIN){
recv(switch_sock, &server_response, sizeof(server_response), 0);
printf("%s\n", server_response);
}
}
}
Creates a TCP Socket for the switch.
int CreateTCPClientSocket( unsigned short port, char *serverAddress){
int sock; /*socket to create */
struct sockaddr_in servAddr; /* Local address */
/* Construct local address structure */
/* Create socket for incoming connections */
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0){
fprintf(stderr,"ERROR: socket() failed\n");
exit(0);
}
memset(&servAddr, 0, sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_port = htons(port);
servAddr.sin_addr.s_addr = inet_addr(serverAddress);
if(connect(sock, (struct sockaddr *)&servAddr, sizeof(struct sockaddr)) <
0){
printf("Error code: %d\n", errno);
fprintf(stderr, "ERROR: connect() just failed\n");
exit(0);
}
return sock;
}
This is the controller
#include "controller.h"
#include "packets.h"
#include "switch.h"
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/select.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
void do_controller(int nSwitch, int portNumber){
int controller_sock; /* Socket descriptor for server/controller */
int clnSocket; /*Socket descriptor for clients */
int activity;
int max_sd;
int sd;
int client_socket[nSwitch];
struct sockaddr_in address;
int addrlen;
/* Controller stuff */
Controller cont;
cont.ackCounter = 0;
cont.openCounter = 0;
Switch sw;
char message[256] = "You have reached the server\n";
char recv_message[20];
printf("\n\nController created: nSwitch: %d on portNumber: %d\n", nSwitch, portNumber);
/* Initialise all client_socket[] to 0 so not checked */
for(int i = 0; i < nSwitch; i++){
client_socket[i] = 0;
}
/*Create the server/controller socket */
controller_sock = CreateTCPServerSocket(portNumber);
//addrlen = sizeof(address);
/* Prepare for nonblocking I/O polling/select from the controller socket */
printf("Starting server.........\n\n");
while(1){
/* Zero the socket set and set for server sockets */
/* This must be reset every time select() is called */
/* Add keyboard to descriptor */
/* Add client and controller sockets to set */
FD_ZERO(&sockSet);
FD_SET(STDIN_FILENO, &sockSet);
FD_SET(controller_sock, &sockSet);
max_sd = controller_sock;
//max_sd = 0;
printf("nSwitch: %d\n", nSwitch);
for(int x = 0; x < nSwitch; x++){
sd = client_socket[x];
printf("sd: %d\n\n", sd);
if(sd > 0)
FD_SET(sd, &sockSet);
if(sd > max_sd)
max_sd = sd;
}
printf("max_sd: %d\n", max_sd);
//wait for one of the sockets, timeout is Null,
//so wait indefinitely
activity = select(max_sd + 1, &sockSet, NULL, NULL,NULL);
//printf("Activity: %d\n", activity);
if(activity < 0){
fprintf(stderr, "ERROR: select()\n");
exit(0);
}
/*Check keyboard */
if(FD_ISSET(STDIN_FILENO, &sockSet)){
int a;
char command[1024][256];
int commands;
char buf[256];
commands = read(0, buf, 256);
buf[commands] = '\0';
char *token;
token = strtok(buf, " ");
while(token != NULL){
strcpy(command[a], token);
a++;
token = strtok(NULL, " ");
}
a = 0;
bzero(buf, 256);
if(strcmp(command[0], "list") == 0){
//TODO: Make a print function
print_controller(&cont, nSwitch);
}
if(strcmp(command[0], "exit") == 0){
//TODO: Make a print function
print_controller(&cont, nSwitch);
exit(0);
}
continue;
}
/* Check the incoming FIFOS from the controller an attached switches */
/*If something happened on the controller socket,
then its an incomming connection. Accept new communitcation.Wait for a client to connect.
Recieve packets sent to the controller_sock
*/
if(FD_ISSET(controller_sock, &sockSet)){
clnSocket = AcceptTCPConnection(controller_sock);
if(send(clnSocket, message, sizeof(message), 0) != sizeof(message)){
fprintf(stderr, "Send()");
exit(0);
}
puts("Welcome message sent successfuly");
//PROBELM HERE BELOW!!!!!!! Returns error code 107 because the
socket disconnected.
recv(controller_sock, &recv_message, sizeof(recv_message), 0);
printf("This is my recv_message: %s\n", recv_message);
/*add new socket to array of sockets*/
for(int a = 0; a < nSwitch; a++){
/*if position is empty */
if(client_socket[a] == 0){
client_socket[a] = clnSocket;
printf("Adding to list of sockets as %d\n", client_socket[a]);
break;
}
}
}
/* Communicate with the sockets and handle TCP Client */
for(int z = 0; z <nSwitch; z++){
sd = client_socket[z];
/*Check if it was socket closed, and do other stuff */
if(FD_ISSET(sd ,&sockSet )){
getpeername(sd , (struct sockaddr*)&address , (socklen_t*)&addrlen);
printf("Host disconnected , ip %s , port %d \n" , inet_ntoa(address.sin_addr) , ntohs(address.sin_port));
close( sd );
client_socket[z] = 0;
}else{
//Do stuff for the client
printf("This is the client %d\n", sd);
}
}
}
}
These are the controllers functions: Assign a port to socket,Set socket to listen
int AcceptTCPConnection(int servSock){
int clntSock; /* Socket descriptor for client */
unsigned int clientAddressLen; /* sizeof(client_address); Length of client */
struct sockaddr_in cli_addr; /* Client address */
/* Set the size of the in-out parameter */
clientAddressLen = sizeof(cli_addr);
printf("ClientAddressLen: %x\n", clientAddressLen);
/* Wait for a client to connect */
if ((clntSock = accept(servSock, (struct sockaddr *) &cli_addr,
&clientAddressLen)) < 0){
fprintf(stderr, "ERROR: accept failed\n");
exit(0);
}
/* clntSock is connected to a client! */
//infrom user of socket number used in send and receive commands
printf("Handling client %s\n", inet_ntoa(cli_addr.sin_addr));
printf("New connection: socket fd is: %d, ip is: %s, port: %d\n\n",
clntSock, inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port));
return clntSock;
}
Create a TCP socket
int CreateTCPServerSocket(unsigned short port){
int sock; /* socket to create */
struct sockaddr_in servAddr; /* Local address */
/* Create socket for incoming connections */
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0){
fprintf(stderr,"ERROR: socket() failed\n");
exit(0);
}
/* Construct local address structure */
/* Define the server address */
//bzero((char *) &server_address, sizeof(server_address));
memset(&servAddr, 0, sizeof(servAddr)); /* Zero out structure */
servAddr.sin_family = AF_INET; /* Internet address family
*/
servAddr.sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface
*/
servAddr.sin_port = htons(port); /* Local port */
/* Bind to the local address */
printf("New connection: ip is: %s, port: %d\n\n",
inet_ntoa(servAddr.sin_addr), ntohs(servAddr.sin_port));
if (bind(sock, (struct sockaddr *) &servAddr, sizeof(servAddr)) < 0){
printf("Error code: %d\n", errno);
fprintf(stderr,"ERROR: bind() just failed\n");
exit(0);
}
/* Mark the socket so it will listen for incoming connections */
if (listen(sock, 5) < 0){
fprintf(stderr,"ERROR: listen() failed\n");
exit(0);
}
return sock;
}

Calculate average of numbers in TCP connection

I have to calculate the average of numbers received by a server, then send it to client in a TCP connection in C. The program must be like this:
Client sends a message to server with numbers(for example): 2 10 12 --> 2 is number of data and 10 and 12 are the data. Server receives the numbers and sends the count of them to client(in this example count is "2"). It continues until client sends number "0". At this point, server has to send a message to client with number of data calculated and, in the same line, the average of them. If i send "2 10 12" and "2 5 6", server sends to client the message: "4 8.25". "4" is the number of data to calculate and "8.25" is average.
Until now i made the first part for client:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
int main(int argc, char *argv[]) {
int simpleSocket = 0;
int simplePort = 0;
int returnStatus= 0;
char buffsend[256];
char buffrecv[256];
char buff[256];
int i, n, length, ndata;
float average=0;
struct sockaddr_in simpleServer;
if (3 != argc) {
fprintf(stderr, "Usage: %s <server> <port>\n", argv[0]);
exit(1);
}
/* create a streaming socket */
simpleSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (simpleSocket == -1) {
fprintf(stderr, "Could not create a socket!\n");
exit(1);
}
else {
fprintf(stderr, "Socket created!\n");
}
/* retrieve the port number for connecting */
simplePort = atoi(argv[2]);
/* setup the address structure */
/* use the IP address sent as an argument for the server address */
//bzero(&simpleServer, sizeof(simpleServer));
memset(&simpleServer, '\0', sizeof(simpleServer));
simpleServer.sin_family = AF_INET;
//inet_addr(argv[2], &simpleServer.sin_addr.s_addr);
simpleServer.sin_addr.s_addr=inet_addr(argv[1]);
simpleServer.sin_port = htons(simplePort);
/* connect to the address and port with our socket */
returnStatus = connect(simpleSocket, (struct sockaddr *)&simpleServer, sizeof(simpleServer));
if (returnStatus == 0) {
fprintf(stderr, "Connect successful!\n");
}
else {
fprintf(stderr, "Could not connect to address!\n");
close(simpleSocket);
exit(1);
}
/* get the message from the server */
do {
bzero(buffsend, 256);
printf("insert num dati or terminate(write '0'): ");
fgets(buffsend,256,stdin);
n=atoi(buffsend);
if(n>6) {
printf("Error\n");
}
else {
length=strlen(buffsend);
for(i=0;i<n;i++) {
printf("insert number: ");
length=strlen(buffsend);
buffsend[length-1]=' ';
fgets(buffsend+length,256-length,stdin);
write(simpleSocket, buffsend, strlen(buffsend));
read(simpleSocket, buffrecv, 256);
}
ndata=atoi(buffrecv);
printf("DT %d\n", ndata);
}
} while((n!=0) && (n>0));
close(simpleSocket);
return 0;
}
And this for server:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
int simpleSocket = 0;
int simplePort = 0;
int returnStatus = 0;
char buff[256];
char message[256];
int n, i, DT;
int count=0;
float average=0;
struct sockaddr_in simpleServer;
if (2 != argc) {
fprintf(stderr, "Usage: %s <port>\n", argv[0]);
exit(1);
}
simpleSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (simpleSocket == -1) {
fprintf(stderr, "Could not create a socket!\n");
exit(1);
}
else {
fprintf(stderr, "Socket created!\n");
}
/* retrieve the port number for listening */
simplePort = atoi(argv[1]);
/* setup the address structure */
/* use INADDR_ANY to bind to all local addresses */
memset(&simpleServer, '\0', sizeof(simpleServer));
simpleServer.sin_family = AF_INET;
simpleServer.sin_addr.s_addr = htonl(INADDR_ANY);
simpleServer.sin_port = htons(simplePort);
/* bind to the address and port with our socket */
returnStatus = bind(simpleSocket,(struct sockaddr *)&simpleServer,sizeof(simpleServer));
if (returnStatus == 0) {
fprintf(stderr, "Bind completed!\n");
}
else {
fprintf(stderr, "Could not bind to address!\n");
close(simpleSocket);
exit(1);
}
/* lets listen on the socket for connections */
returnStatus = listen(simpleSocket, 5);
if (returnStatus == -1) {
fprintf(stderr, "Cannot listen on socket!\n");
close(simpleSocket);
exit(1);
}
while (1)
{
struct sockaddr_in clientName = { 0 };
int simpleChildSocket = 0;
int clientNameLength = sizeof(clientName);
/* wait here */
simpleChildSocket = accept(simpleSocket,(struct sockaddr *)&clientName, &clientNameLength);
if (simpleChildSocket == -1) {
fprintf(stderr, "Cannot accept connections!\n");
close(simpleSocket);
exit(1);
}
/* handle the new connection request */
/* write out our message to the client */
do {
read(simpleChildSocket, buff, 256);
num=atoi(buff);
conta++;
DT=(conta)-1;
DT=write(simpleChildSocket, buff, strlen(buff));
printf("Message received: %s\n", buff);
bzero(buff, 256);
} while(num!=0);
close(simpleChildSocket);
}
close(simpleSocket);
return 0;
}
There are some fixes in your code, especially on the client side. It is more convenient to send a package with |size| |data| at once, than each number.
The server side receives the packet, reads the size and accumulates, reads the data and accumulates and then sends size to the client.
If the client sends 0, the server calculates the average and sends the result.
I believe it will serve as the initial idea.
cliente side, main loop:
/*--------cliente side---------*/
int iResult;/*iResult >1 get from connect*/
char buffsend[256];
char szTmp[50];
do {
menset(buffsend,0,256);/*zero memory*/
menset(szTmp,0,50);/*zero memory*/
printf("insert num dati or terminate(write '0'): ");
fgets(szTmp,50,stdin);
int n = atoi(szTmp);
if(n>6)
printf("Error\n");
else
{
sprintf(buffsend,"%d ",n);
for(int h=0;h<n;h++)
{
printf("insert number: ");
fgets(szTmp,50,stdin);
szTmp[strcspn(szTmp, "\n")] = 0;/*<---remove end line */
strcat(buffsend,szTmp);/*concatenate new num*/
strcat(buffsend," ");/*add space*/
}
}
/*send the data <len><space><data> exemp: 2 12 34*/
iResult = write( ConnectSocket, buffsend, strlen(buffsend) );
if (iResult == -1)
{
printf("send failed with error: -1\n");
close(ConnectSocket);
return 1;
}
menset(buffsend,0,256);/*zero memory*/
iResult = read(ConnectSocket, buffsend, 256);
if ( iResult > 0 )
printf("Bytes received: %d > %s \n", iResult,recvbuf);
else if ( iResult == 0 )
printf("Connection closed\n");
else
printf("recv failed with error: %d\n", WSAGetLastError());
} while( iResult > 0 );
server side loop:
/*-------------server side------------*/
int iResult;/*At this point iResult is greater than 0, by the return of connect*/
int nNumerator;
int den;/*Accumulate sizes*/
float faverage;
nNumerator=0;
den = 0;
faverage=0;
do
{
memset(recvbuf,0,256);
iResult = read(ClientSocket, recvbuf, recvbuflen);
if (iResult > 0)
{
char bufftmp[25];
int numpart;
int iTmp;
numpart =0;
iTmp =0;
memset(bufftmp,0,25);
printf("Bytes received: %d\n", iResult);
printf("%s\n",recvbuf);
/*Traverses all received datar ecvbuf and separates the accumulating size into den,
and then accumulates the data in nNumerator*/
for(int k=0;k<iResult;k++)
{
bufftmp[iTmp++]=recvbuf[k];
if(recvbuf[k]==' ')
{
if(!numpart)/*is numpart zero*/
{
bufftmp[iTmp]='\0';//make space null
numpart=atoi(bufftmp);
den+=numpart;/*acumalate to average*/
printf("lenght: %d\n",numpart);/*get only length*/
memset(bufftmp,0,25);
if(numpart==0)
{
/*go to average*/
faverage = (float)nNumerator/(float)den;
}
}
else/* if numparte > 0 get data*/
{
bufftmp[iTmp]='\0';
printf("%s ",bufftmp);
nNumerator+=atoi(bufftmp);/*save in to buffer of int´s*/
memset(bufftmp,0,25);
}
iTmp=0;
printf("\n");
}
}
memset(recvbuf,0,256);
if(numpart)/*if not zero, send length of data to client*/
sprintf(recvbuf,"%d",numpart);
else/*if not, send average*/
sprintf(recvbuf,"%d %f",den,faverage);
iResult = write( ClientSocket, recvbuf, strlen(recvbuf));
if (iResult == -1)
{
printf("send failed with error: -1\n");
close(ClientSocket);
return 1;
}
}
else if (iResult == 0)
printf("Connection closing...\n");
else
{
printf("recv failed with error: -1\n");
close(ClientSocket);
return 1;
}
}while (iResult > 0);

Server is not accepting connection from Client side to read data from a file

I want to read a file on Server from the Client application on Linux. I have mentioned below my Server and Client application.
On Client side I open a file (which is necessary to my requirements).
The Client receive the data which I have written on the file. Now, I want to send the received data from Client to the Server side and get back the echo to the Client.
I am facing trouble with the Server to accept the Client connection. I am glad to have a solution, where I made mistake exactly. I also appreciate If I get the solution for the code. Thanks in advance.
Server.C
#include<stdio.h>
#define BufferLength 100
/* Server port number */
#define SERVPORT 3389
int main(int argc, char *argv[])
{
/* Variable and structure definitions. */
int sd, sd2, rc, length = sizeof(int);
int totalcnt = 0, on = 1;
char temp;
char buffer[BufferLength];
//char data[BufferLength];
struct sockaddr_in serveraddr;
struct sockaddr_in their_addr;
fd_set read_fd;
struct timeval timeout;
timeout.tv_sec = 15;
timeout.tv_usec = 0;
/*To read xillybus*/
// FILE *fp;
// fp = fopen("/dev/xillybus_read_8", "r");
// if(fp==NULL)
// {
// printf("Error file open\n");
// exit(-1);
// }
// else{
// printf("File found %s\n", fp);
// }
/* Get a socket descriptor */
if((sd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("Server-socket() error");
exit (-1);
}
else
{
printf("Server-socket() is OK\n");
}
/* Allow socket descriptor to be reusable */
if((rc = setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on))) < 0)
{
perror("Server-setsockopt() error");
close(sd);
exit (-1);
}
else
{
printf("Server-setsockopt() is OK\n");
}
/* bind to an address */
memset(&serveraddr, 0x00, sizeof(struct sockaddr_in));
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(SERVPORT);
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
printf("Using %s, listening at %d\n", inet_ntoa(serveraddr.sin_addr), SERVPORT);
if((rc = bind(sd, (struct sockaddr *)&serveraddr, sizeof(serveraddr))) < 0)
{
perror("Server-bind() error");
close(sd);
exit(-1);
}
else
{
printf("Server-bind() is OK\n");
}
/* Up to 10 clients can be queued */
if((rc = listen(sd, 10)) < 0)
{
perror("Server-listen() error");
close(sd);
exit (-1);
}
else
{
printf("Server-Ready for client connection...\n");
}
/* accept() the incoming connection request. */
int sin_size = sizeof(struct sockaddr_in);
if((sd2 = accept(sd, (struct sockaddr *)&their_addr, &sin_size)) < 0)
{
perror("Server-accept() error");
close(sd);
exit (-1);
}
else
{
printf("Server-accept() is OK\n");
}
/*client IP*/
printf("Server-new socket, sd2 is OK...\n");
printf("Got connection from the client: %s\n", inet_ntoa(their_addr.sin_addr));
/* Wait for up to 15 seconds on */
/* select() for data to be read. */
FD_ZERO(&read_fd);
FD_SET(sd2, &read_fd);
rc = select(sd2+1, &read_fd, NULL, NULL, &timeout);
if((rc == 1) && (FD_ISSET(sd2, &read_fd)))
{
/* Read data from the client. */
totalcnt = 0;
while(totalcnt < BufferLength)
{
/* read() from client */
rc = read(sd2, &buffer[totalcnt], (BufferLength - totalcnt));
if(rc < 0)
{
perror("Server-read() error");
close(sd);
close(sd2);
exit (-1);
}
else if (rc == 0)
{
printf("Client program has issued a close()\n");
close(sd);
close(sd2);
exit(-1);
}
else
{
totalcnt += rc;
printf("Server-read() is OK\n");
}
}
}
else if (rc < 0)
{
perror("Server-select() error");
close(sd);
close(sd2);
exit(-1);
}
/* rc == 0 */
else
{
printf("Server-select() timed out.\n");
close(sd);
close(sd2);
exit(-1);
}
/* Shows the data */
printf("Received data from the client: %s\n", buffer);
printf("Server-Echoing back to client...\n");
/*Write function*/
rc = write(sd2, buffer, totalcnt);
if(rc != totalcnt)
{
perror("Server-write() error");
rc = getsockopt(sd2, SOL_SOCKET, SO_ERROR, &temp, &length);
if(rc == 0)
{
/* Print out the asynchronously */
/* received error. */
errno = temp;
perror("SO_ERROR was: ");
}
else
{
printf("Server-write() is OK\n");
}
close(sd);
close(sd2);
exit(-1);
}
/******************************************/
close(sd2);
close(sd);
exit(0);
return 0;
}
Client.c
#include<stdio.h>
#define BufferLength 100
#define SERVER "00.00.00.00"
/* Server's port number */
#define SERVPORT 3389
/* set the server name in the #define SERVER ... */
int main(int argc, char *argv[])
{
/* Variable and structure definitions. */
int sd, rc, length = sizeof(int);
struct sockaddr_in serveraddr;
char buffer[BufferLength];
char server[255];
char temp;
int totalcnt = 0;
struct hostent *hostp;
//char data[500] = "Hello ravi !!! "; // writes data to the server
/*To open directory and read the xillybus*/
FILE *fp;
char s[100];
fp = fopen("/dev/xillybus_read_8", "r");
if(!fp)
return 1;
while(fgets(s,100,fp)!=NULL){
printf("%s ", s);
}
//fclose(fp);
/******************************************/
/* get a socket descriptor */
if((sd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("Client-socket() error");
exit(-1);
}
else
{
printf("Client-socket() OK\n");
}
/*If the server hostname is supplied*/
if(argc > 1)
{
/*Use the supplied argument*/
strcpy(server, argv[1]);
printf("Connecting to the server %s, port %d ...\n", server, SERVPORT);
}
else
{
/*Use the default server name or IP*/
strcpy(server, SERVER);
memset(&serveraddr, 0x00, sizeof(struct sockaddr_in));
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(SERVPORT);
}
if((serveraddr.sin_addr.s_addr = inet_addr(server)) == (unsigned long)INADDR_NONE)
{
/* get host address */
hostp = gethostbyname(server);
if(hostp == (struct hostent *)NULL)
{
printf("HOST NOT FOUND --> ");
/* h_errno is usually defined */
/* in netdb.h */
printf("h_errno = %d\n",h_errno);
printf("---This is a client program---\n");
printf("Command usage: %s <server name or IP>\n", argv[0]);
close(sd);
exit(-1);
}
memcpy(&serveraddr.sin_addr, hostp->h_addr, sizeof(serveraddr.sin_addr));
}
/* connect() to server. */
if((rc = connect(sd, (struct sockaddr *)&serveraddr, sizeof(serveraddr))) < 0)
{
perror("Client-connect() error");
close(sd);
exit(-1);
}
else
{
printf("Connection established...\n");
printf("Sending some string to the server %s...\n", server);
}
/* Write() some string to the server. */
//rc = write(sd, data, sizeof(data));
rc = write(sd,fp, sizeof(fp)); // here is my write function
if(rc < 0)
{
perror("Client-write() error");
rc = getsockopt(sd, SOL_SOCKET, SO_ERROR, &temp, &length);
if(rc == 0)
{
/* Print out the asynchronously received error. */
errno = temp;
perror("SO_ERROR was");
}
close(sd);
exit(-1);
}
else
{
printf("Client-write() is OK\n");
printf("String successfully sent \n");
printf("Waiting the %s to echo back...\n", server);
}
totalcnt = 0;
/* Read data from the server. */
while(totalcnt < BufferLength)
{
rc = read(sd, &buffer[totalcnt], BufferLength-totalcnt); //&buffer[totalcnt],BufferLength-totalcnt
if(rc < 0)
{
perror("Client-read() error");
close(sd);
exit(-1);
}
else if (rc == 0)
{
printf("Server program has issued a close()\n");
close(sd);
exit(-1);
}
else
{
totalcnt += rc;
}
}
printf("Client-read() is OK\n");
printf("Echoed data from the server: %s\n", buffer); //data ->buffer
/* Close socket descriptor from client side. */
close(sd);
exit(0);
return 0;
}
In you client.c program, you try to send a FILE* to the server. What you are sending is the address of the file descriptor in client program and not the text contained in the file.
You send only 4 or 8 bytes (depending on architecture 32 or 64 bits), while server waits for at least 100 bytes before echoing anything. So both programs do exactly what you programmed - but not what you expected.
To send the content of a file, you read the file in a char array and send the char array. You can iterate over the file reading one buffer at a time and sending the buffer. But there is no magic allowing to send a whole file.

Resources