variable length message over tcp - c

I am trying to send variable length message in TCP but the message length that
is printed is always 0. I am using beej guide code for send and receive and pack and unpack to send the header length.Can someone please point out the mistake.
server code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define MAX_SIZE 50
void error(const char *msg)
{
perror(msg);
exit(1);
}
void packi32(unsigned char *buf, unsigned long i)//from beej guide
{
*buf++ = i>>24; *buf++ = i>>16;
*buf++ = i>>8; *buf++ = i;
}
/* sends all data - thanks to Beej's Guide to Network Programming */
int sendall(int s, char *buf, int *len)
{
int total=0;
int bytesleft=*len;
int n=0;
/* send all the data */
while(total<*len){
/* send some data */
n=send(s,buf+total,bytesleft,0);
/* break on error */
if(n==-1)
break;
/* apply bytes we sent */
total+=n;
bytesleft-=n;
}
/* return number of bytes actually send here */
*len=total;
/* return -1 on failure, 0 on success */
return n==-1?-1:0;
}
int sendus(int s,char *msg)
{
char buf[4];//here 4 is header length
int len = strlen(msg);
packi32(buf,len);
int ll = 4;// ll is header length containing message length
int x;
if((x = sendall(s,buf,&ll))< 0)
printf("value of sent x %d\n",x);
int y = sendall(s,msg,&len);
return y;
}
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno;
socklen_t clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n;
if (argc < 2)
{
fprintf(stderr,"ERROR, no port provided\n");
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
error("ERROR on binding");
listen(sockfd,5);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0)
error("ERROR on accept");
char msg[1024] = "hello";
int xx = sendus(sockfd,(char*)msg);
close(newsockfd);
close(sockfd);
return 0;
}
client code
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include<errno.h>
void error(const char *msg)
{
perror(msg);
exit(0);
}
/** unpacki32() -- unpack a 32-bit int from a char buffer (like ntohl())
*/
unsigned long unpacki32(unsigned char *buf)
{
return (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
}
/* receives all data - modelled after sendall() */
int recvall(int s, char *buf, int *len, int timeout){
int total=0;
int bytesleft=*len;
int n=0;
time_t start_time;
time_t current_time;
/* clear the receive buffer */
bzero(buf,*len);
time(&start_time);
/* receive all data */
while(total<*len){
/* receive some data */
n=recv(s,buf+total,bytesleft,0);
/* no data has arrived yet (non-blocking socket) */
if(n==-1 && errno==EAGAIN){
time(&current_time);
if(current_time-start_time>timeout)
break;
sleep(1);
continue;
}
/* receive error or client disconnect */
else if(n<=0)
break;
/* apply bytes we received */
total+=n;
bytesleft-=n;
}
/* return number of bytes actually received here */
*len=total;
/* return <=0 on failure, bytes received on success */
return (n<=0)?n:total;
}
int recvme(int s, char *buf)
{
char len[4];
int l = 4;
int n = recvall(s,len,&l,10);
int msg_len = unpacki32(len);
printf("msg_length :%d",msg_len);
int z ;
z = recvall(s,buf,&msg_len,10);
return z;
}
int main(int argc, char *argv[])
{
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[1024];
if (argc < 3)
{
fprintf(stderr,"usage %s hostname port\n", argv[0]);
exit(0);
}
portno = atoi(argv[2]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
server = gethostbyname(argv[1]);
if (server == NULL)
{
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons(portno);
if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
error("ERROR connecting");
n = recvme(sockfd, buffer);
if (n < 0)
error("ERROR reading from socket");
printf("%s\n",buffer);
close(sockfd);
return 0;
}

The basic cause for the failure is in the server's line
int xx = sendus(sockfd,(char*)msg);
- sockfd is the listen() socket, but we have to use the newsockfd returned from accept(), i. e.
sendus(newsockfd, msg);

Related

Send file size and then the file itself

client-side code:
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#include <netdb.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
void error(char * msg){
perror(msg);
exit(0);
}
// Returns an string array from function
char *buff(const char *path){
int end = 0;
unsigned char * buf;
int f_write = open(path,O_RDONLY);
end = lseek(f_write,0,SEEK_END);
lseek(f_write,0,SEEK_SET);
buf =(char*)malloc(sizeof(char*)*(end+1));
read(f_write,buf,end);
close(f_write);
buf[end+1]= '\0';
return buf;
}
//connects to the socket
int connection(int portno,struct hostent * server,int sockfd){
struct sockaddr_in serv_addr;
int conn =0;
bzero((char *)&serv_addr,sizeof(serv_addr));
serv_addr.sin_family= AF_INET;
bcopy((char*)server->h_addr,(char *)&serv_addr.sin_addr.s_addr,server->h_length);
serv_addr.sin_port = htons(portno);
conn = connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr));
return conn;
}
int main(int argc, char *argv[]) {
int sockfd = -1;
int check =0;
char projname[100]= "project1";
int portno = -1;
int conn = -1;
int file_size =0;
ssize_t len;
int n = -1;
struct hostent *server;
char buffer[256];
int fd =0;
if(argc < 3){
fprintf(stderr,"usage %s hostname port\n",argv[0]);
exit(0);
}
// getting the portnumber
portno = atoi(argv[2]);
sockfd = socket(AF_INET,SOCK_STREAM,0);
if(sockfd < 0){
error("Error opening socket");
}
// getting the hostname
server = gethostbyname(argv[1]);
if(server == NULL){
fprintf(stderr,"Error no such host\n");
exit(0);
}
conn = connection(portno,server,sockfd);
if(conn < 0){
printf("%s\n",strerror(errno));
}
int path = open("text.txt",O_CREAT | O_WRONLY, 0644);
if(path < 0){
printf("%s\n",strerror(errno));
}
int remain_data = file_size;
printf("Printing out the file size ");
printf("%d\n",file_size);
char *buffer1 = (char*)malloc(sizeof(char)*file_size+1);
len = recv(sockfd,buffer1,BUFSIZ,0);
printf("%d",len);
buffer1[file_size]= '\0';
printf("printing the sentence\n");
printf("%s\n",buffer1);
int total_read_bytes =0;
int nread =0;
return 0;
}
server-side code
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#include <dirent.h>
#include <fcntl.h>
#include <sys/sendfile.h>
#include <sys/stat.h>
#include <sys/socket.h>
void error(char * msg){
perror(msg);
exit(1);
}
int main(int argc, char const *argv[]){
int sockfd =-1;
int newsockfd = -1;
int portno = -1;
int clilen = -1;
int remain_data =0;
char buffer[300];
char buffer1[300];
int peer_socket = -1;
struct sockaddr_in serv_addr,cli_addr;
int n = -1;
struct stat file_stat;
char file_size[256];
ssize_t len;
int sent_bytes =0;
int path = open("project1/text.txt",O_RDONLY);
read(path,buffer1,30);
buffer1[31]= '\0';
printf("%s\n",buffer1);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd <0){
error("Error opening socket");
}
bzero((char*) &serv_addr,sizeof(serv_addr));
portno=atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if(bind(sockfd,(struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0){
error("Error on Binding");
}
listen(sockfd,5);
int fd = open("project1/text.txt",O_RDONLY);
fstat(fd,&file_stat);
clilen = sizeof(cli_addr);
peer_socket = accept(sockfd,(struct sockaddr *)&cli_addr, &clilen);
sprintf(file_size,"%d",file_stat.st_size);
//sends file size
len = send(peer_socket,file_size,sizeof(file_size),0);
if(peer_socket <0){
error("Error on accept");
}
off_t offset = 0;
remain_data = file_stat.st_size;
//send the file
while(((sent_bytes=sendfile(peer_socket,fd,&offset,remain_data))>0) &&( remain_data>0)){
fprintf(stdout,"1.Server sent %d bytes from files data, offset is now : %d and remaining data = %d\n",sent_bytes, offset,remain_data);
remain_data -=sent_bytes;
fprintf(stdout, "2. Server sent %d bytes from files data, offest is not: %d and remaing data = %d\n",sent_bytes, offset,remain_data);
}
return 0;
}
I am able to get the size of my file from server side but I am unable to get file content from my server on client side. My client prints out an empty space where the data of the file is supposed to be, I don't know if I am using the recv function correctly the file correctly.
P.S I understand that I must close the sockets when finished.
For safety and robustness, you must check the return values of all the standard library functions you call to check for errors. For recv() and read(), however, you must check and appropriately handle return values for correctness. These functions do not guarantee to transfer the full number of bytes requested, and for network connections it is reasonably common that they don't. If you want to fully transfer a specific number of bytes then you must be prepared to use multiple recv() or read() calls to do so, generally by calling the function in a loop.
You do not check the return value of your recv() call, so if you have a short read -- or if there is an error or if the remote side closes the connection without sending anything -- then your client will not notice, and will simply output whatever garbage happens to be in the buffer.

I want to include a for loop in the code below which can continuously send data id, timestamp and message at interval of every n seconds

This is the client program where the intended for loop has to be set. But i am not able to understand where to include it as i am new to socket programming. Please someone help me code it. I need this code to include a loop which will help me continuously transfer random data to the server in every n seconds.
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
void error(char *msg)
{
perror(msg);
exit(0);
}
int main(int argc, char *argv[])
{
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[256];
if (argc < 3) {
fprintf(stderr,"usage %s hostname port\n", argv[0]);
exit(0);
}
portno = atoi(argv[2]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
server = gethostbyname(argv[1]);
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons(portno);
if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0)
error("ERROR connecting");
printf("Please enter the message: ");
bzero(buffer,256);
fgets(buffer,255,stdin);
n = write(sockfd,buffer,strlen(buffer));
if (n < 0)
error("ERROR writing to socket");
bzero(buffer,256);
n = read(sockfd,buffer,255);
if (n < 0)
error("ERROR reading from socket");
printf("%s\n",buffer);
return 0;
}
Add #include<time.h> at the beggining.
Use the function given below to add delay.
void delay(unsigned short secs)
{
unsigned milli_seconds = 1000 * secs;
clock_t start_time = clock(); //declaration in time.h
while (clock() < start_time + milli_seconds)
;
}
Inside main() call the delay(interval) in infinite loop to send timestamp, id and
int main(int argc, char *argv[])
{
unsigned data_id=0;
char data[1024];
...
while(1)
{
delay(5);
send(client_sock,data,strlen(data),0);
}
..
return EXIT_SUCCESS;
}
I hope you get it.
Note: Do not use bzero() instead use memset(). For more read this one.

Issue using c sockets with threads to read from and write to the socket

I want to write a TCP server-client chat, but when I start the two threads for reading from and writing to a socket at both sides, I think they block each other out. Can anyone help me with this?
Server Code:
/* A simple server in the internet domain using TCP the port number is passed as an argument */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <pthread.h>
struct server_args_runner{
char buffer [256];
int newsockfd;
pthread_t tid;
pthread_attr_t attr;
//read/write attribute (read == 0 and write == 1)
int rw;
};
void error(char *msg){
perror(msg);
exit(1);
}
void* server_runner_fun(void* args){
// this is the chat part!
// get args:
int n;
struct server_args_runner *sar = (struct server_args_runner*) args;
if(sar->rw == 0){
printf("server thread trys to read from socket...\n");
//read-part
while(1){
bzero(sar->buffer, 256);
n = read(sar->newsockfd, sar->buffer, 255);
if (n < 0){
error("ERROR reading from socket");
}
}
printf("%s\n", sar->buffer);
} else {
printf("server thread trys to write to socket...\n");
//write-part
while(1){
bzero(sar->buffer, 256);
fgets(sar->buffer, 255, stdin);
n = write(sar->newsockfd, sar->buffer, strlen((char *) &(sar->buffer)));
if (n < 0){
error("ERROR writing to socket");
}
}
}
}
int main(int argc, char *argv[]){
//fd = filedescriptor
int sockfd, portno, clilen;
struct sockaddr_in serv_addr, cli_addr;
int n;
if (argc < 2){
fprintf(stderr,"ERROR, no port provided\n");
exit(1);
}
//socket(...) returns a descriptor
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1){
error("ERROR opening socket");
}
printf("Socket created successfully.\n");
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
//htons(..) converts the short from hostbyteorder to networkbyteorder
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr,sizeof(serv_addr)) == -1){
error("ERROR on binding");
}
printf("binding successfull on port %d\n", portno);
listen(sockfd, 2);
clilen = sizeof(cli_addr);
printf("server is listening ...\n");
struct server_args_runner server_write_t, server_read_t;
server_write_t.newsockfd = accept(sockfd,(struct sockaddr *) &cli_addr, &clilen);
printf("server accepted connection to client.\n");
if (server_write_t.newsockfd < 0){
error("ERROR on accept");
}
//initializing both server_threads
pthread_attr_init(&server_write_t.attr);
pthread_attr_init(&server_read_t.attr);
server_write_t.rw = 1;
server_read_t.rw = 0;
bcopy(&server_write_t.newsockfd, &server_read_t.newsockfd, sizeof(server_write_t.newsockfd));
pthread_create(&server_write_t.tid, &server_write_t.attr, server_runner_fun, &server_write_t);
pthread_create(&server_read_t.tid, &server_read_t.attr, server_runner_fun, &server_read_t);
pthread_join(server_write_t.tid, NULL);
pthread_join(server_read_t.tid, NULL);
return 0;
}
Client code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <pthread.h>
struct client_args_runner{
char buffer [256];
int sockfd;
pthread_t tid;
pthread_attr_t attr;
//read/write attribute (read == 0 and write == 1)
int rw;
};
void error(char *msg){
perror(msg);
exit(0);
}
void* client_runner_fun(void* args){
// this is the chat part!
// get args:
int n;
struct client_args_runner *car = (struct client_args_runner*) args;
if(car->rw == 0){
printf("client thread trys to read from socket...\n");
//read-part
while(1){
bzero(car->buffer, 256);
n = read(car->sockfd, car->buffer, 255);
if (n < 0){
error("ERROR reading from socket");
}
}
printf("%s\n", car->buffer);
} else {
printf("client thread trys to write to socket...\n");
//write-part
while(1){
bzero(car->buffer, 256);
fgets(car->buffer, 255, stdin);
n = write(car->sockfd, car->buffer, strlen((char *) &(car->buffer)));
if (n < 0){
error("ERROR writing to socket");
}
}
}
}
int main(int argc, char *argv[]){
int portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
if (argc < 3){
fprintf(stderr,"usage %s hostname port\n", argv[0]);
exit(0);
}
portno = atoi(argv[2]);
struct client_args_runner client_write_t, client_read_t;
client_write_t.sockfd = socket(AF_INET, SOCK_STREAM, 0);
bcopy(&client_write_t.sockfd, &client_read_t.sockfd,
sizeof(client_write_t.sockfd));
if (client_write_t.sockfd == -1){
error("ERROR on creating socket_file_descriptor");
}
printf("socket created successfully.\n");
server = gethostbyname(argv[1]);
printf("hostname is valid.\n");
if(server == NULL){
fprintf(stderr, "Error, no such host\n");
exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *) server->h_addr, (char *) &serv_addr.sin_addr.s_addr, server->h_length);
serv_addr.sin_port = htons(portno);
printf("before connecting to client..\n");
if (connect(client_write_t.sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) == -1){
error("ERROR connecting");
}
printf("client connected successfully to server.\n");
//initializing both client_threads
pthread_attr_init(&client_write_t.attr);
pthread_attr_init(&client_read_t.attr);
client_write_t.rw = 1;
client_read_t.rw = 0;
pthread_create(&client_write_t.tid, &client_write_t.attr, client_runner_fun, &client_write_t);
pthread_create(&client_read_t.tid, &client_read_t.attr, client_runner_fun, &client_read_t);
pthread_join(client_write_t.tid, NULL);
pthread_join(client_read_t.tid, NULL);
return 0;
}
Your printfs in both the client and server readers are outside the while(1) loops, so your client and server are communicating fine, you just aren't printing anything you read from the sockets.

simple client server in c

i am not able to understand why the code is not working. sendall and revcall are taken from beej guide. Their is no output when i send the data from server to client. Can someone please explain the error in code. It is mostly from beej guide.One of the problems in broken pipe i.e reading when port is closed but when the port is closed i am not able to understand.
server code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define MAX_SIZE 50
void error(const char *msg)
{
perror(msg);
exit(1);
}
/* sends all data - thanks to Beej's Guide to Network Programming */
int sendall(int s, char *buf, int *len)
{
int total=0;
int bytesleft=*len;
int n=0;
/* send all the data */
while(total<*len)
{
/* send some data */
n=send(s,buf+total,bytesleft,0);
/* break on error */
if(n==-1)
break;
/* apply bytes we sent */
total+=n;
bytesleft-=n;
}
/* return number of bytes actually send here */
*len=total;
/* return -1 on failure, 0 on success */
return n==-1?-1:0;
}
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno;
socklen_t clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n;
if (argc < 2)
{
fprintf(stderr,"ERROR, no port provided\n");
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
printf("sockfd : %d",sockfd);
if (sockfd < 0)
error("ERROR opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if(bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
error("ERROR on binding");
listen(sockfd,5);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0)
error("ERROR on accept");
char msg[1024] = "hello";
int len = sizeof(msg);
int xx = sendall(sockfd,(char*)msg,&len);
close(newsockfd);
close(sockfd);
return 0;
}
client code
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include<errno.h>
void error(const char *msg)
{
perror(msg);
exit(0);
}
/* receives all data - modelled after sendall() */
int recvall(int s, char *buf, int *len, int timeout)
{
int total=0;
int bytesleft=*len;
int n=0;
time_t start_time;
time_t current_time;
/* clear the receive buffer */
bzero(buf,*len);
time(&start_time);
/* receive all data */
while(total<*len)
{
/* receive some data */
n=recv(s,buf+total,bytesleft,0);
/* no data has arrived yet (non-blocking socket) */
if(n==-1 && errno==EAGAIN)
{
time(&current_time);
if(current_time-start_time>timeout)
break;
sleep(1);
continue;
}
/* receive error or client disconnect */
else if(n<=0)
break;
/* apply bytes we received */
total+=n;
bytesleft-=n;
}
/* return number of bytes actually received here */
*len=total;
/* return <=0 on failure, bytes received on success */
return (n<=0)?n:total;
}
int main(int argc, char *argv[])
{
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[1024];
if (argc < 3)
{
fprintf(stderr,"usage %s hostname port\n", argv[0]);
exit(0);
}
portno = atoi(argv[2]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");;
serv_addr.sin_port = htons(portno);
if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
error("ERROR connecting");
int m = 1024;
n = recvall(sockfd, buffer,&m,10);
if (n < 0)
error("ERROR reading from socket");
printf("%s\n",buffer);
close(sockfd);
return 0;
}
'int xx = sendall(sockfd,(char*)msg,&len);'
'sockfd' is the server listening socket. You should be calling sendall() with 'newsockfd', as returned by the accept() call.

Simple TCP server with multiple clients C/unix

I'm having problems understanding socket programming and need some help. I am suppose to modify my server code that I have written to accept 3 clients. I know I am suppose to use a fork for each client, but I am not sure how to implement this into my code. Here is my original code that I wrote for one client. Any help would be appreciated.
Server:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
void error(const char *msg)
{
perror(msg);
exit(1);
}
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno;
socklen_t clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n;
if (argc < 2) {
fprintf(stderr,"ERROR, no port provided\n");
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0)
error("ERROR on binding");
listen(sockfd,5);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd,
(struct sockaddr *) &cli_addr,
&clilen);
if (newsockfd < 0)
error("ERROR on accept");
bzero(buffer,256);
n = read(newsockfd,buffer,255);
if (n < 0) error("ERROR reading from socket");
printf("Here is the message: %s\n",buffer);
n = write(newsockfd,"I got your message",18);
if (n < 0) error("ERROR writing to socket");
close(newsockfd);
close(sockfd);
return 0;
}
Client:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
void error(const char *msg)
{
perror(msg);
exit(0);
}
int main(int argc, char *argv[])
{
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[256];
if (argc < 3) {
fprintf(stderr,"usage %s hostname port\n", argv[0]);
exit(0);
}
portno = atoi(argv[2]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
server = gethostbyname(argv[1]);
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons(portno);
//printf("h_addr: %s\n", inet_ntoa(serv_addr.sin_addr));
if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
error("ERROR connecting");
printf("Please enter the message: ");
bzero(buffer,256);
fgets(buffer,255,stdin);
n = write(sockfd,buffer,strlen(buffer));
if (n < 0)
error("ERROR writing to socket");
bzero(buffer,256);
n = read(sockfd,buffer,255);
if (n < 0)
error("ERROR reading from socket");
printf("%s\n",buffer);
close(sockfd);
return 0;
}
Here is your's modified server code to handle multiple clients using fork
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
void error(const char *msg) {
perror(msg);
exit(1);
}
int main(int argc, char *argv[]) {
int sockfd, newsockfd, portno;
socklen_t clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n;
if (argc < 2) {
fprintf(stderr, "ERROR, no port provided\n");
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
error("ERROR on binding");
listen(sockfd, 5);
clilen = sizeof(cli_addr);
//Below code is modified to handle multiple clients using fork
//------------------------------------------------------------------
int pid;
while (1) {
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0)
error("ERROR on accept");
//fork new process
pid = fork();
if (pid < 0) {
error("ERROR in new process creation");
}
if (pid == 0) {
//child process
close(sockfd);
//do whatever you want
bzero(buffer, 256);
n = read(newsockfd, buffer, 255);
if (n < 0)
error("ERROR reading from socket");
printf("Here is the message: %s\n", buffer);
n = write(newsockfd, "I got your message", 18);
if (n < 0)
error("ERROR writing to socket");
close(newsockfd);
} else {
//parent process
close(newsockfd);
}
}
//-------------------------------------------------------------------
return 0;
}
Server.c
#define RUNNING_DIR "/tmp "
define LOCK_FILE "exampled.lock"
#define LOG_FILE "exampled.log"
#include <fcntl.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <errno.h>
#include <time.h>
#include <string.h>
#define MAXCLIENT 100
#define TRUE 1
#define FALSE 0
#define MINUTE 5
struct Client
{
char name[256];
char *clientAddr;
int fd;
};
int client;
int i;
int minute;
struct Client p[100];
void remove_client(int);
int search_addr(char [],int *);
void log_message(filename,message)
char *filename;
char *message;
{
FILE *logfile;
logfile=fopen(filename,"a");
if(!logfile) return;
fprintf(logfile,"%s\n",message);
fclose(logfile);
}
void catch_int(sig)
int sig;
{
log_message(LOG_FILE,strsignal(sig));
}
void daemonize()
{
int i,lfp,lfp1;
char str[10];
signal(SIGINT, catch_int);
for ( i=0;i<65;i++)
{
if ( i!=32 && i!=33 )
if (signal(i, SIG_IGN) != SIG_IGN)
signal(i, catch_int);
}
if(getppid()==1) return; /* already a daemon */
i=fork();
if (i<0) exit(1); /* fork error */
if (i>0) exit(0); /* parent exits */
/* child (daemon) continues */
setsid(); /* obtain a new process group */
for (i=getdtablesize();i>=0;--i) close(i); /* close all descriptors */
i=open("/dev/null",O_RDWR); dup(i); dup(i); /* handle standart I/O */
umask(027); /* set newly created file permissions */
chdir(RUNNING_DIR); /* change running directory */
lfp=open(LOCK_FILE,O_RDWR|O_CREAT,0640);
lfp1=open(LOG_FILE,O_RDWR|O_CREAT,0640);
if (lfp<0) exit(1); /* can not open */
if (lockf(lfp,F_TLOCK,0)<0) exit(0); /* can not lock */
/* first instance continues */
sprintf(str,"%d\n",getpid());
write(lfp,str,strlen(str)); /* record pid to lockfile */
}
int main()
{
daemonize();
time_t rawtime;
struct tm *info;
time(&rawtime);
info = localtime(&rawtime );
minute=MINUTE + info->tm_min;
int server_sockfd, client_sockfd;
int server_len, client_len;
struct sockaddr_in server_address;
struct sockaddr_in client_address;
int result;
fd_set readfds, testfds;
server_sockfd = socket(AF_INET, SOCK_STREAM, 0);
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = htonl(INADDR_ANY);
server_address.sin_port = htons(5000);
server_len = sizeof(server_address);
bind(server_sockfd, (struct sockaddr *)&server_address, server_len);
listen(server_sockfd, 5);
FD_ZERO(&readfds);
FD_SET(server_sockfd, &readfds);
while(1) {
char ch;
int fd;
int nread;
testfds = readfds;
result = select(FD_SETSIZE,&testfds,NULL,NULL,NULL);
if(result < 1) {
perror("server5");
exit(1);
}
for(fd = 0; fd < FD_SETSIZE; fd++) {
time(&rawtime);
info = localtime(&rawtime );
if(FD_ISSET(fd,&testfds)) {
if(fd == server_sockfd) {
int j=0;
char Clients[1096];
memset( Clients, '\0', sizeof(Clients) );
client_len = sizeof(client_address);
client_sockfd = accept(server_sockfd,
(struct sockaddr *)&client_address, &client_len);
client++;
char *sAddress = inet_ntoa(client_address.sin_addr);
p[i].clientAddr=strdup(sAddress);
sprintf(p[i].name,"client%d",client);
p[i].fd=client_sockfd;
for (j =0; j < client; j++)
{
strcat(Clients,p[j].clientAddr);
strcat(Clients," ");
strcat(Clients,p[j].name);
strcat(Clients,"\n");
}
for ( j=0; j < client ; j++)
{
send(p[j].fd,Clients,strlen(Clients),0);
}
i++;
FD_SET(client_sockfd, &readfds);
}
else {
ioctl(fd, FIONREAD, &nread);
if(nread == 0) {
close(fd);
remove_client(fd);
FD_CLR(fd, &readfds);
}
else {
char addr[100];
char *msg;
char sucess[]="Message from Ip Address:";
int n;
int des=0;
int found;
n=recv(fd,addr,sizeof(addr),0);
addr[n]='\0';
strtok_r (addr, "\n", &msg);
found=search_addr(addr,&des);
if ( found )
{
strcat(sucess,addr);
send(fd,"Message Has been
sucessfully sended\n",36,0);
strcat(sucess,"\n");
strcat(sucess,msg);
send(des,sucess,strlen(sucess),0);
}
else
{
send(fd,"Message Sending Failed..\n",27,0);
}
sleep(5);
}
}
}
if ( minute == info->tm_min)
{
int j=0;
char Clients[1096];
memset( Clients, '\0', sizeof(Clients) );
sprintf(Clients,"Now Currently Available ip:\n");
for (j =0; j < client; j++)
{
strcat(Clients,p[j].clientAddr);
strcat(Clients," ");
strcat(Clients,p[j].name);
strcat(Clients,"\n");
}
for ( j=0; j < client ; j++)
{
send(p[j].fd,Clients,strlen(Clients),0);
}
minute=minute+MINUTE;
}
}
}
}
void remove_client(int fd)
{
int j=0;
int pos;
for ( j=0; j< client ; j++)
{
if ( p[j].fd == fd )
{
pos=j;
break;
}
}
for ( j=pos+1 ; j < client ; j++)
{
sscanf( p[j].name, "%s",p[pos].name);
p[pos].clientAddr=p[j].clientAddr;
p[pos].fd=p[j].fd;
pos++;
}
client--;
i--;
}
int search_addr(char address[],int *des)
{
char *name;
int j;
char temp_addr[100];
strcpy(temp_addr,address);
strtok_r (temp_addr, " ", &name);
for ( j=0; j< client ; j++ )
{
if ( (strcmp(temp_addr,p[j].clientAddr)==0) && (strcmp(name,p[j].name)==0))
{
*des=p[j].fd;
return TRUE;
}
}
return FALSE;
}
Client.c
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>
// #define SERVERIP "192.168.12.61"
#define PORT 5000
#include <setjmp.h>
#define MAXSLEEP 128
int main(int argc, char *argv[])
{
int Response=1;
int sockfd = 0, n = 0;
char recvBuff[1024];
struct sockaddr_in serv_addr;
jmp_buf env;
if(argc != 2)
{
printf("\n Usage: %s <ip of server> \n",argv[0]);
return 1;
}
memset(recvBuff, '0',sizeof(recvBuff));
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("\n Error : Could not create socket \n");
return 1;
}
memset(&serv_addr, '0', sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
if(inet_pton(AF_INET, argv[1], &serv_addr.sin_addr)<=0)
{
printf("\n inet_pton error occured\n");
return 1;
}
setjmp(env);
if (connect_retry ( sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr) )< 0 )
{
printf("Time Limited Exceeded....\n ");
return 0;
}
for (;;) {
char str[100];
char addr[100];
if ( Response == 1 )
{
int z = recv(sockfd,recvBuff,sizeof(recvBuff),0); //MSG_DONTWAIT
if ( z == -1 )
{
}
else if ( z == 0 )
{
printf("Server Failed ....\n");
longjmp(env, 2);
break;
}
else
{
recvBuff[z] = 0;
printf("'%s'",recvBuff);
sleep(1);
}
}
else
{
int z = recv(sockfd,recvBuff,sizeof(recvBuff),MSG_DONTWAIT); //MSG_DONTWAIT
if ( z == -1 )
{
}
else if ( z == 0 )
{
printf("Server Failed...\n");
longjmp(env, 2);
break;
}
else
{
recvBuff[z] = 0;
printf("'%s'",recvBuff);
sleep(1);
}
}
fd_set rfdset;
FD_ZERO(&rfdset);
struct timeval tv;
tv.tv_sec = 10;
tv.tv_usec = 0;
FD_SET(STDIN_FILENO, &rfdset);
int bReady = select(STDIN_FILENO+1,&rfdset,NULL,NULL,&tv);
if (bReady > 0)
{
// printf("Chat with Client Address: \n");
if( fgets (addr, 4096, stdin)!=NULL ) {
}
printf("Enter Message:\n");
if( fgets (str, 4096, stdin)!=NULL ) {
}
strcat(addr,str);
send(sockfd,addr,strlen(addr),0);
}
Response=0;
}
return 0;
}
int
connect_retry(int sockfd, const struct sockaddr *addr, socklen_t alen)
{
int nsec;
/*
* * Try to connect with exponential backoff.
* */
for (nsec = 1; nsec <= MAXSLEEP; nsec <<= 1) {
if (connect(sockfd, addr, alen) == 0) {
/*
* * Connection accepted.
* */
return(0);
}
/*
* * Delay before trying again.
* */
printf("Waiting For Server....\n");
if (nsec <= MAXSLEEP/2)
sleep(nsec);
}
return(-1);
}
server send the ipaddress of new client connection and each few minutes
192.168.12.61 client1
ENter the msg
Hello

Resources