Skip to content

Instantly share code, notes, and snippets.

@khanzf
Last active September 14, 2015 01:31
Show Gist options
  • Save khanzf/4cfdf19af62462d93057 to your computer and use it in GitHub Desktop.
Save khanzf/4cfdf19af62462d93057 to your computer and use it in GitHub Desktop.
Multiserv
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <arpa/inet.h>
struct clientinfo {
int fd;
struct sockaddr_in info;
};
int rmfd(struct clientinfo *connects, int location, int numcon) {
int count;
struct clientinfo *temp;
for(count=location;count<=numcon;count++)
connects[count] = connects[count+1];
temp = malloc(sizeof(struct clientinfo)*(numcon-1+(numcon-1==0)));
for(count=0;count<numcon-1;count++) {
temp[count] = connects[count];
}
connects = malloc(sizeof(struct clientinfo)*(numcon-1+(numcon-1==0)));
for(count=0;count<numcon-1;count++) {
connects[count] = temp[count];
}
return numcon-1;
}
int addfd(struct clientinfo *connects, int numcon) {
struct clientinfo *temp;
int count;
temp = malloc(sizeof(struct clientinfo) * (numcon+(numcon==0)));
for(count=0;count<numcon;count++) {
temp[count].fd = connects[count].fd;
temp[count].info = connects[count].info;
}
connects = malloc(sizeof(struct clientinfo)*(numcon+1));
for(count=0;count<numcon;count++) {
connects[count].fd = temp[count].fd;
connects[count].info = temp[count].info;
}
return numcon+1;
}
int main(int argc, char **argv) {
int check;
int sin_size;
int numcon;
int maxfd;
int readtest;
int writecount;
char rwbuf[1024];
struct timeval timer;
struct clientinfo *connects;
fd_set sockrd;
if (argc != 2) {
fprintf(stderr, "usage: %s port\n", argv[0]);
exit(-1);
}
sin_size = sizeof(struct sockaddr);
numcon = 0;
connects = malloc(sizeof(struct clientinfo));
FD_ZERO(&sockrd);
connects[0].info.sin_family = AF_INET;
connects[0].info.sin_port = htons(atoi(argv[1]));
connects[0].info.sin_addr.s_addr = INADDR_ANY;
connects[0].fd = socket(AF_INET, SOCK_STREAM, 0);
check = bind(connects[0].fd, (struct sockaddr *)&connects[0].info, sizeof(struct sockaddr));
if(check == -1) {
perror("bind");
exit(check);
}
check = listen(connects[0].fd, 1024);
if (check == -1) {
perror("listen");
exit(check);
}
maxfd = connects[0].fd;
for(;;) {
FD_ZERO(&sockrd);
FD_SET(connects[0].fd, &sockrd);
for(check=1;check<=numcon;check++)
FD_SET(connects[check].fd, &sockrd);
timer.tv_sec = 60;
timer.tv_usec = 0;
select(maxfd+1, &sockrd, NULL, NULL, &timer);
if (FD_ISSET(connects[0].fd, &sockrd)) {
sin_size = sizeof(struct sockaddr_in);
numcon = addfd(connects, numcon);
connects[numcon].fd = accept(connects[0].fd, (struct sockaddr *)&connects[numcon].info, &sin_size);
if (connects[numcon].fd > maxfd)
maxfd = connects[numcon].fd;
}
else {
for(readtest=1;readtest<=numcon;readtest++) {
if(FD_ISSET(connects[readtest].fd, &sockrd)) {
memset(rwbuf, 0, 1024);
check = read(connects[readtest].fd, rwbuf, 1024);
if (check == 0) {
close(connects[readtest].fd);
numcon = rmfd(connects, readtest, numcon);
}
else {
for(writecount=1;writecount<=numcon;writecount++) {
if (writecount != readtest)
write(connects[writecount].fd, rwbuf, 1024);
}
}
}
}
}
}
}
@khanzf
Copy link
Author

khanzf commented Sep 14, 2015

This code handles multiple IPv4 sockets and relays data from one to the rest. It does not utilize fork(2).

I wrote this as the frame for a chat program I had planned on writing back in 2001, but never finished. However, I was quite happy with this snippet of code.

I doubt it has any practical application, especially in modern computing environments where distributed frameworks use multi-threading, but I hope it serves as an effective teaching tool.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment