Simple TCP server with multiple clients C/unix - c

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

Related

Problems sending messages to a server using TCP sockets

I'm trying to send messages to a server, but when I connect, the server immediately fails receiving the message. It seems that the server "does not wait" for the user to type the message. The server is supposed to remain in that while loop, forever waiting for clients and printing their messages.
I have no idea what's wrong.
Server code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <pthread.h>
#define PORT 4000
#define WORD_SIZE 256
#define USER_SOCKETS 2
#define MAX_USERS 10
int receiveMessage(int socket, char message[])
{
int bytesReceived;
while (1)
{
bytesReceived = recv(socket, message, WORD_SIZE, 0);
if (bytesReceived < 0)
return -1;
if (bytesReceived == 0)
return 0;
}
}
int main(int argc, char *argv[])
{
int serverSockfd;
socklen_t clilen;
struct sockaddr_in serv_addr, cli_addr;
if ((serverSockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
printf("Error creating the socket.\n");
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
serv_addr.sin_addr.s_addr = INADDR_ANY;
bzero(&(serv_addr.sin_zero), 8);
if (bind(serverSockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
printf("Error binding the socket..\n");
return -1;
}
if (listen(serverSockfd, 5) < 0)
{
printf("Error on listening.\n");
return -1;
}
int newSockfd;
while (1)
{
if (newSockfd = accept(serverSockfd, (struct sockaddr *)&cli_addr, &clilen) < 0)
{
printf("Error on accept a new client.\n");
continue;
}
char username[WORD_SIZE];
if (receiveMessage(newSockfd, username) < 0)
{
printf("Error receiving message.\n");
close(newSockfd);
}
printf("Message: %s\n", username);
close(newSockfd);
}
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>
#define PORT 4000
int main(int argc, char * argv[]) {
int sockfd, n;
struct sockaddr_in serv_addr;
struct hostent * server;
char buffer[256];
if (argc < 2) {
fprintf(stderr, "usage %s hostname\n", argv[0]);
exit(0);
}
server = gethostbyname(argv[1]);
if (server == NULL) {
fprintf(stderr, "ERROR, no such host\n");
exit(0);
}
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
printf("ERROR opening socket\n");
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
serv_addr.sin_addr = * ((struct in_addr * ) server -> h_addr);
bzero( & (serv_addr.sin_zero), 8);
if (connect(sockfd, (struct sockaddr * ) & serv_addr, sizeof(serv_addr)) < 0)
printf("ERROR connecting\n");
printf("Enter the message: ");
bzero(buffer, 256);
fgets(buffer, 256, stdin);
/* write in the socket */
n = write(sockfd, buffer, strlen(buffer));
if (n < 0)
printf("ERROR writing to socket\n");
bzero(buffer, 256);
printf("%s\n", buffer);
close(sockfd);
return 0;
}
The line:
if (newSockfd = accept(serverSockfd, (struct sockaddr *)&cli_addr, &clilen) < 0)
will set newSockfd to 0 if accept() succeeds, rather than to the descriptor of the socket. This is because < has a higher precedence than =, so the compiler behaves as-if you had written this:
if (newSockfd = (accept(serverSockfd, (struct sockaddr *)&cli_addr, &clilen) < 0))
You need to write this instead:
if ((newSockfd = accept(serverSockfd, (struct sockaddr *)&cli_addr, &clilen)) < 0)

communication between client and server,executiolg commands

I am trying to do a command line, based on socket communication.My only problem is that after exexvp is executed (and the data are being printed on the client's side), the client close and i want to keep him alive.
This is my code:
client.c
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#include <sys/types.h>
#include <netdb.h>
#define PORT_NUMBER 1754
#define HOST_NUMBER
void error(const char *msg)
{
perror(msg);
exit(0);
}
int main(int argc, char *argv[])
{
int sockfd, port_number, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[256];
if (argc < 3) {
//fprintf(stderr, "usage %s hostname port\n", argv[0]);
//first parameter is ip address
printf("usage %s hostname port\n", argv[0]);
exit(0);
}
port_number = atoi(argv[2]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0 )
error("ERROR opening socket!Socket failed!");
printf("Trying to connect...\n");
server = gethostbyname(argv[1]); //ip address
if (server == NULL) {
error( "ERROR, no such host");
//fprintf(stderr, "ERROR, no such host\n"); exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET; //AF_UNIX
bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length);
serv_addr.sin_port = htons(port_number);
if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
error("ERROR connecting");
printf("Connected!\n");
printf("%s_>\n",argv[1]);
while(1) {
printf("Please enter the message: "); //THE CLIENT MUST WRITE A COMMAND
fgets(buffer, 256, stdin); //apo stdin sto buffer
n = write(sockfd, buffer, strlen(buffer)); //apo buffer sto socket
if(n < 0 ) {
error("ERROR writing to socket");
}
bzero(buffer, 256);
if ( recv(sockfd, buffer, 256, 0) < 0) {
printf("Server closed connection\n");
}
printf("%s\n", buffer);
}
return 0;
}
sever.c
#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 <arpa/inet.h>
#include <signal.h>
#include <sys/wait.h>
#include <errno.h>
void parse(char *vector_args[20], char *buffer){
buffer[strcspn(buffer, "\n")] =0;
int i=0;
char * pch;
pch = strtok (buffer," ");
while (pch != NULL )
{
vector_args[i]=pch;
printf (" %s\n",pch);
pch = strtok (NULL, " ");
i++;
}
vector_args[i]=NULL;
int k=0;
for(k=0; k<=i; k++) {
printf("vector %d = %s \n",k,vector_args[k]);
}
}
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;
char str[INET_ADDRSTRLEN];
char *vector_args[20];
int status;
char *fd[2];
if (argc < 2)
{
fprintf(stderr, "No port provided\n");
exit(1);
}
unlink("sockfd"); //remove any old socket
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");
int l = listen(sockfd, 5);
if (l < 0)
{
error("listen failed!");
}
clilen = sizeof(cli_addr);
printf( "Server waiting for a connection...\n " );
while(1) {
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0)
error("ERROR on accept");
if (inet_ntop(AF_INET, &cli_addr.sin_addr, str, INET_ADDRSTRLEN) == NULL) {
fprintf(stderr, "Could not convert byte to address\n");
exit(1);
}
fprintf(stdout, "Connected!\nThe client address is :%s\n", str);
//fork new process
int pid = fork();
if (pid == -1 ) {
error("ERROR in new process creation");
close(newsockfd);
continue;
}else if( pid != 0){
//parent process
close(newsockfd);//h edw h prin to continue
printf( " I am parent process %d\n " ,getpid()); //BGALE
if (wait(&status)== -1) /* Wait for child*/
{
perror( " wait " );
}
check_child_exit(status);
continue;
}else if (pid == 0) {
//child process
close(sockfd);
bzero(buffer, 256);
while(1) {
n = read(newsockfd, buffer, 255); //apo socket ston buffer
if (n < 0 )
error("ERROR reading from socket");
printf("Here is the message: %s\n", buffer);
n = write(newsockfd, "I got your message", 18);
bzero(buffer, 256);
close(1); //close stdin
dup2( newsockfd, 1);
close(0); //close stdout
dup2( newsockfd, 0);
parse(vector_args,buffer);
execvp(vector_args[0] , vector_args );
perror( " execvp " );
exit(EXIT_FAILURE);
bzero(buffer, 256);
}
close(newsockfd);
break;
}
}
}
Do you have any ideas how could I change my code in order to work properly?
The loop
while (1) {
....
execvp(....);
}
is effectively executed once. The reason is that the successful execvp replaces the code with whatever vector_args requests, and the executed process just exits when done.
If I understand your goals correctly (one process per connection, executing external commands in the loop), you need one more fork, along the lines of
while (1) {
....
if ((pid = fork()) == 0) {
execvp(....);
} else if (pid > 0) {
waitpid(....);
} else {
handle_error();
}
}
If client send pwd, server may recv p w d or pw d or pwd and so on.
In my opinion, if client want to send pwd, client should send pwd\n, server will read command until \n. If server want to send 123, server should send 123\0, client will read until \0. I write a tiny example, you could learn from it. The server code will continue until client quit.
server.c
#include <arpa/inet.h>
#include <errno.h>
#include <netinet/in.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
void parse(char** argv, char* buffer) {
int i = 0;
argv[i] = strtok(buffer, " ");
while (argv[i] != NULL) argv[++i] = strtok(NULL, " ");
}
void handle_client(int con_socket) {
for (;;) {
char buf[1024];
ssize_t i = 0;
for (;;) {
ssize_t ret = read(con_socket, buf + i, 1);
if (ret == 0) return;
if (buf[i] == '\n') {
buf[i] = '\0';
break;
}
++i;
}
int pipe_fd[2];
pipe(pipe_fd);
if (fork() == 0) {
close(con_socket);
dup2(pipe_fd[1], 1);
close(pipe_fd[0]);
close(pipe_fd[1]);
char* argv[25];
parse(argv, buf);
execvp(argv[0], argv);
exit(EXIT_FAILURE);
} else {
close(pipe_fd[1]);
for (;;) {
ssize_t ret = read(pipe_fd[0], buf, sizeof(buf));
if (ret == 0) {
write(con_socket, "", 1);
break;
}
write(con_socket, buf, ret);
}
wait(NULL);
}
}
}
int main() {
const char* server_ip = "127.0.0.1";
uint16_t server_port = 6666;
struct sockaddr_in server_addr;
bzero(&server_addr, sizeof server_addr);
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(server_port);
inet_pton(AF_INET, server_ip, &server_addr.sin_addr);
int listen_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
int opt = 1;
setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
bind(listen_socket, (struct sockaddr*)(&server_addr),
(socklen_t)(sizeof server_addr));
listen(listen_socket, 5);
for (;;) {
int con_socket = accept(listen_socket, NULL, NULL);
if (fork() > 0) {
close(con_socket);
wait(NULL);
continue;
} else {
close(listen_socket);
handle_client(con_socket);
close(con_socket);
break;
}
}
return 0;
}
client.c
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
int main() {
const char* server_ip = "127.0.0.1";
uint16_t server_port = 6666;
struct sockaddr_in server_addr;
bzero(&server_addr, sizeof server_addr);
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(server_port);
inet_pton(AF_INET, server_ip, &server_addr.sin_addr);
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));
for (;;) {
printf(">> ");
char buffer[256];
fgets(buffer, 256, stdin);
if (strlen(buffer) == 0) continue;
write(sockfd, buffer, strlen(buffer));
for (;;) {
ssize_t ret = recv(sockfd, buffer, 256, 0);
buffer[ret] = '\0';
printf("%s", buffer);
if (buffer[ret - 1] == '\0') break;
}
}
return 0;
}

Problematic socket server

I'm trying to create a server-client socket scenario, in which more than one clients communicate with a server through socket. Server reads the data and sends back some acknowledgement and parallel saves some data.
My server.c code:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
void serve(int);
struct data {
int checked;
int all;
}Data;
int main(int argc, char *argv[]) {
int sockfd, newsockfd, portno;
struct sockaddr_in serv_addr, cli_addr;
int pid;
socklen_t clilen;
if (argc < 2) {
fprintf(stderr,"ERROR: NO PORT PROVIDED!\n");
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
fprintf(stderr,"ERROR: CANNOT CREATE SOCKET!\n");
exit(1);
}
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) {
fprintf(stderr,"ERROR: CANNOT BIND CONNECTION!\n");
exit(1);
}
listen(sockfd,5);
clilen = sizeof(cli_addr);
while (1) {
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0) {
fprintf(stderr,"ERROR: CANNOT ACCEPT NEW CONNECTION!\n");
exit(1);
}
pid = fork();
if (pid < 0) {
fprintf(stderr,"ERROR: CANNOT CREATE NEW PROCESS!\n");
exit(1);
}
if (pid == 0) {
close(sockfd);
serve(newsockfd);
exit(0);
}
else
close(newsockfd);
}
return 0;
}
void serve(int new) {
int n;
int buffer[256];
int sum = 0;
int m = 0;
int i = 0;
int size = 0;
bzero(buffer, 256);
n = read(new, buffer, 256);
if (n == NULL) {
fprintf(stderr, "ERROR: CANNOT READ FROM CLIENT!\n");
exit(1);
}
do {
size++;
i++;
}while (buffer[i] != 0);
for (i = 0; i < size; i++)
sum += buffer[i];
m = sum / size;
sum = 0;
if (m > 10) {
Data.checked++;
Data.all++;
n = write(new, "Sequence OK", 11);
if (n == NULL) {
fprintf(stderr, "ERROR: CANNOT WRITE TO CLIENT!\n");
exit(1);
}
} else {
Data.all++;
n = write(new, "Check failed", 12);
}
printf("Data so far:\n1)Number of sequences received: %d\n2)Number of sequences with average above 10: %d\n", Data.all, Data.checked);
}
And my client.c code is:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#include <memory.h>
int main(int argc, char *argv[]) {
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
int buffer[256];
char buffer2[13];
char answer;
int i;
int size = 0;
if (argc < 3) {
fprintf(stderr,"ERROR: CANNOT USE %s PORT!\n", argv[0]);
exit(0);
}
portno = atoi(argv[2]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0){
fprintf(stderr, "ERROR: CANNOT CREATE SOCKET!\n");
exit(1);
}
server = gethostbyname(argv[1]);
if (server == NULL) {
fprintf(stderr,"ERROR: NO HOST FOUND!\n");
exit(1);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy(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) {
fprintf(stderr, "ERROR: CANNOT CONNECT TO SERVER!\n");
exit(1);
}
do {
bzero(buffer, 256);
printf("Give the numbers now and enter 0 to stop\n");
for (i = 0; i < 256; i++) {
scanf("%d", &buffer[i]);
if (buffer[i] == 0)
break;
}
do {
size++;
i++;
}while (buffer[i] != 0);
n = write(sockfd, buffer, size);
if (n < 0) {
fprintf(stderr, "ERROR: CANNOT WRITE TO SERVER!\n");
exit(1);
}
bzero(buffer2, 13);
n = read(sockfd, buffer2, 13);
if (n < 0) {
fprintf(stderr, "ERROR: CANNOT READ FROM CLIENT!\n");
exit(1);
}
printf("%s\n", buffer2);
printf("Do you want to enter another sequence?\ty (yes) || n (no)\n");
scanf(" %c", &answer);
system("clear");
}while (answer == 'y');
return 0;
}
So the problem is that the server works with different clients (multiple terminals), but will not work with the same client after the first time. I'm new to this whole server-client thing so I'm struggling a bit. Does anyone have an idea?
Thanks in advance.

TCP/IP : Transmission not working after string operations

I'm trying to simulate a simple TCP connection between a client and a server, on the localhost. Things are working well without line 22 on "client.c" file, where I'm doing a string operation. With that line un-commented, the server apparently does not make the connection with the client.
I've been searching around for quite long, but I found nothing strictly related to this. It'd be great if I got some help. :)
Files:
client.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <unistd.h>
#define BUFLEN 256
void error(char *msg)
{
perror(msg);
exit(0);
}
int main(int argc, char *argv[])
{
int sockfd, n;
//char filename[] = "file.txt"; // !!THE PROBLEM IS HERE!!
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[BUFLEN];
if (argc < 3) {
fprintf(stderr,"Usage %s server_address server_port\n", argv[0]);
exit(0);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(atoi(argv[2]));
inet_aton(argv[1], &serv_addr.sin_addr);
if (connect(sockfd,(struct sockaddr*) &serv_addr,sizeof(serv_addr)) < 0)
error("ERROR connecting");
while(1) {
memset(buffer, 0 , BUFLEN);
fgets(buffer, BUFLEN-1, stdin);
n = send(sockfd,buffer,strlen(buffer), 0);
if (n < 0)
error("ERROR writing to socket");
}
return 0;
}
server.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#define MAX_CLIENTS 5
#define BUFLEN 256
void error(char *msg)
{
perror(msg);
exit(1);
}
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno, clilen;
char buffer[BUFLEN];
struct sockaddr_in serv_addr, cli_addr;
int n, i, j;
fd_set read_fds;
fd_set tmp_fds;
int fdmax;
if (argc < 2) {
fprintf(stderr,"Usage : %s port\n", argv[0]);
exit(1);
}
FD_ZERO(&read_fds);
FD_ZERO(&tmp_fds);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
portno = atoi(argv[1]);
memset((char *) &serv_addr, 0, sizeof(serv_addr));
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(struct sockaddr)) < 0)
error("ERROR on binding");
listen(sockfd, MAX_CLIENTS);
FD_SET(sockfd, &read_fds);
fdmax = sockfd;
// main loop
while (1) {
tmp_fds = read_fds;
if (select(fdmax + 1, &tmp_fds, NULL, NULL, NULL) == -1)
error("ERROR in select");
for(i = 0; i <= fdmax; i++) {
if (FD_ISSET(i, &tmp_fds)) {
if (i == sockfd) {
clilen = sizeof(cli_addr);
if ((newsockfd = accept(sockfd, (struct sockaddr *)&cli_addr, &clilen)) == -1) {
error("ERROR in accept");
}
else {
FD_SET(newsockfd, &read_fds);
if (newsockfd > fdmax) {
fdmax = newsockfd;
}
}
printf("New connection from IP %s, port %d, socket_client %d\n ", inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port), newsockfd);
}
else {
memset(buffer, 0, BUFLEN);
if ((n = recv(i, buffer, sizeof(buffer), 0)) <= 0) {
if (n == 0) {
printf("selectserver: socket %d hung up\n", i);
} else {
error("ERROR in recv");
}
close(i);
FD_CLR(i, &read_fds);
}
else { //recv > 0
printf ("I received from the client with socket %d, this message: %s\n", i, buffer);
}
}
}
}
}
close(sockfd);
return 0;
}
Compiling:
gcc client.c -o client
gcc server.c -o server
Running (in different terminals):
./server 9999
./client localhost 9999

Multithreaded client-server chat application in c language

I wrote an application for communicating between two clients (one will run the server.c application, and the other one client.c).
Everything goes very good at this point, both sides (client and server) can send and receive messages (there are two processes in both sides: one for listening and printing messages, and one for receiving and sending back messages).
There is what I got so far:
client.c
#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 <signal.h>
#include "aes.h"
#define BSIZE 320
uint8_t key[] = "qwertyuioplkjhg";
uint8_t iv[] = "123456789098765";
void error(const char *msg) {
perror(msg);
exit(0);
}
int main(int argc, char *argv[]) {
int sockfd, portno, n, pid;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[BSIZE];
char paddedData[BSIZE];
unsigned char crypted_data[BSIZE];
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");
}
//while(1) {
switch(pid = fork()) {
case -1:
error("ERROR fork");
case 0:
while(1) {
//printf("Please enter the message: ");
bzero(buffer, BSIZE);
//printf("Message: ");
fgets(buffer, BSIZE - 1, stdin);
strncpy(paddedData, buffer, BSIZE);
AES128_CBC_encrypt_buffer(crypted_data, (unsigned char*)paddedData, BSIZE, key, iv);
n = write(sockfd, crypted_data, BSIZE - 1);
if(n < 0) {
error("ERROR writing to socket");
}
}
default:
while(1) {
//bzero(buffer,256);
n = read(sockfd, buffer, BSIZE - 1);
AES128_CBC_decrypt_buffer((unsigned char*)paddedData, (unsigned char*)buffer, BSIZE, key, iv);
if(n < 0) {
error("ERROR reading from socket");
}
printf("<<server>>: %s", paddedData);
}
}
close(sockfd);
return 0;
}
and server.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include "aes.h"
#define BSIZE 320
uint8_t key[] = "qwertyuioplkjhg";
uint8_t iv[] = "123456789098765";
int numberOfConnections = 0;
void communications_handler(int);
void error(const char *msg) {
perror(msg);
exit(1);
}
int main(int argc, char *argv[]) {
int sockfd, newsockfd, portno, pid;
socklen_t clilen;
struct sockaddr_in serv_addr, cli_addr;
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);
while(1) {
/* [1] */
newsockfd = accept(sockfd, (struct sockaddr*)&cli_addr, &clilen);
numberOfConnections++;
printf("\nThere are %d clients connected!\n\n", numberOfConnections);
if (newsockfd < 0) {
error("ERROR on accept");
}
pid = fork();
if (pid < 0) {
error("ERROR on fork");
}
if (pid == 0) {
close(sockfd);
communications_handler(newsockfd);
exit(0);
}
else {
close(newsockfd);
}
}
close(sockfd);
return 0;
}
void communications_handler(int sock) {
int n, pid;
char buffer[BSIZE];
char paddedData[BSIZE];
unsigned char crypted_data[BSIZE];
switch(pid = fork()) {
case -1:
error("ERROR on fork");
case 0:
while(1) {
n = read(sock, buffer, BSIZE - 1);
AES128_CBC_decrypt_buffer((unsigned char*)paddedData, (unsigned char*)buffer, BSIZE, key, iv);
if(n < 0) {
error("ERROR reading from socket");
}
printf("<<client>>: %s", paddedData);
}
default:
while(1) {
bzero(buffer, BSIZE);
//printf("Message: ");
fgets(buffer, BSIZE - 1, stdin);
strncpy(paddedData, buffer, BSIZE);
AES128_CBC_encrypt_buffer(crypted_data, (unsigned char*)paddedData, BSIZE, key, iv);
for(int i = 0; i < numberOfConnections; i++) {
n = write(sock, crypted_data, BSIZE - 1);
}
if(n < 0) {
error("ERROR writing to socket");
}
}
}
}
Now I want to extend this program, by letting the server to accept multiple connections (I actually did this, in server.c, at [1]).
But there is now one problem: How can I implement the communication between two (or more) clients (the server will only accept new connections, read data from all connected clients, and send data back to all clients).
Can this be done with processes?
Have a look at Beej's guide to non-blocking socket programming: http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html#select

Resources