communication between client and server,executiolg commands - c

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;
}

Related

modify c socket program to send file from server to client

Modify the following socket program and let the server send a file to the client.
I'm stuck with this i can't figure this out.
below is the server and client that where given to me. right now the server will send the client the time stamp.
Socket Server Example (server.c)
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>
int main(int argc, char *argv[])
{
int listenfd = 0, connfd = 0;
struct sockaddr_in serv_addr;
char sendBuff[1025];
time_t ticks;
listenfd = socket(AF_INET, SOCK_STREAM, 0);
memset(&serv_addr, '0', sizeof(serv_addr));
memset(sendBuff, '0', sizeof(sendBuff));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(5000);
bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
listen(listenfd, 10);
while(1)
{
connfd = accept(listenfd, (struct sockaddr*)NULL, NULL);
ticks = time(NULL);
snprintf(sendBuff, sizeof(sendBuff), "%.24s\r\n",
ctime(&ticks));
write(connfd, sendBuff, strlen(sendBuff));
close(connfd);
sleep(1);
}
}
Socket Client Example (client.c)
#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>
int main(int argc, char *argv[])
{
int sockfd = 0, n = 0;
char recvBuff[1024];
struct sockaddr_in serv_addr;
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(5000);
if(inet_pton(AF_INET, argv[1], &serv_addr.sin_addr)<=0)
{
printf("\n inet_pton error occured\n");
return 1;
}
if( connect(sockfd, (struct sockaddr *)&serv_addr,
sizeof(serv_addr)) < 0)
{
printf("\n Error : Connect Failed \n");
return 1;
}
while ( (n = read(sockfd, recvBuff, sizeof(recvBuff)-1)) > 0)
{
recvBuff[n] = 0;
if(fputs(recvBuff, stdout) == EOF)
{
printf("\n Error : Fputs error\n");
}
}
if(n < 0)
{
printf("\n Read error \n");
}
return 0;
}
If you don't want to or can't read the whole content of the file you wish to send at once into memory, use a loop with your buffer:
#include <fcntl.h>
if (argv[1]) // or whereever you get the file name from
{
int fd = open(argv[1], O_RDONLY);
if (fd < 0) perror(argv[1]);
else
{
ssize_t n;
while (n = read(fd, sendBuff, sizeof sendBuff), n > 0)
if (send(connfd, sendBuff, n, MSG_NOSIGNAL) < 0)
{ perror("send"); break; }
close(fd);
if (n < 0) perror("read");
}
}
In the client use a similar loop. Be aware that the file might contain NUL characters, so functions like fputs, operating on C strings, are inept.
while ((n = read(sockfd, recvBuff, sizeof recvBuff)) > 0)
if (write(1, recvBuff, n) < 0) perror("write");
Read the content of the file you wish to send, and save it into a string:
char *loadFileContent(char *fileName, size_t *len){
FILE* input_file = fopen(fileName, "rb");
size_t stat;
if(!input_file){
OCSP_ERR_INDEX = OCSP_LOG_ERR_load_file_fail;
return NULL;
}
fseek(input_file, 0, SEEK_END);
long int input_file_size = ftell(input_file);
rewind(input_file);
char *file_contents = malloc((input_file_size + 1) * (sizeof(char)));
stat = fread(file_contents, sizeof(char), (size_t) input_file_size, input_file);
if(stat<1){
OCSP_ERR_INDEX = OCSP_LOG_ERR_load_file_fail;
return NULL;
}
fclose(input_file);
file_contents[input_file_size] = 0;
*len = (size_t) input_file_size;
return file_contents;
}
In your code, modify the line in server that is supposed to send response to client.
So this line write(connfd, sendBuff, strlen(sendBuff)); becomes:
size_t len;
char *text = loadFileContent("myfile.txt", &len);
write(connfd, text, len);

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

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