Ok Hier mal den gesammten Code.
Nein kein fork. Es wird über select geregelt!
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/fcntl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <unistd.h>
struct list_entry {
int sock;
struct list_entry *next;
};
struct list_type {
struct list_entry *data;
unsigned count;
};
#define BUF_SIZ 4096
#define PORT 7000
void init_list(struct list_type *list)
{
list->data = NULL;
list->count = 0;
}
int add_client(struct list_type *list, int sock)
{
struct list_entry *n;
n = malloc(sizeof(*n));
if (!n)
{
perror("malloc() failed");
return 1;
}
n->sock = sock;
n -> next = list->data;
list->data = n;
list->count++;
return 0;
}
int remove_client(struct list_type *list, int sock)
{
struct list_entry *lz, *lst = NULL;
if (!list->count)
return 1;
for (lz = list->data; lz; lz = lz->next)
{
if (lz->sock == sock)
break;
lst = lz;
}
if (!lz)
return 1;
if (lst)
lst->next = lz->next;
else
list->data = lz->next;
free(lz);
list->count--;
return 0;
}
int fill_set(fd_set *fds, struct list_type *list)
{
int max = 0;
struct list_entry *lz;
for (lz = list->data; lz; lz = lz->next)
{
if (lz->sock > max)
max = lz->sock;
FD_SET(lz->sock, fds);
}
return max;
}
int get_sender(fd_set *fds)
{
int i = 0;
while(!FD_ISSET(i, fds))
i++;
return i;
}
/* Sonderfall: STDIN_FILENO muss natuerlich auf STDOUT_FILENO
* beschrieben werden.
*/
int send_all(char *msg, int len, struct list_type *list, int sender)
{
struct list_entry *lz;
for (lz = list->data; lz; lz = lz->next)
{
if (lz->sock == sender)
continue;
if (lz->sock == STDIN_FILENO)
write(STDOUT_FILENO, msg, len);
else
write(lz->sock, msg, len);
}
return 0;
}
int main_loop(int s)
{
int c, max, sender, bytes;
fd_set fds;
struct list_type list;
char buf[BUF_SIZ];
init_list(&list);
add_client(&list, STDIN_FILENO);
for(;;)
{
FD_ZERO(&fds);
max = fill_set(&fds, &list);
FD_SET(s, &fds);
if (s > max)
max = s;
select(max + 1, &fds, NULL, NULL, NULL);
if (FD_ISSET(s, &fds))
{
c = accept(s, NULL, 0);
add_client(&list, c);
}
else
{
sender = get_sender(&fds);
bytes = read(sender, buf, sizeof(buf));
if (bytes == 0)
remove_client(&list, sender);
else
send_all(buf, bytes, &list, sender);
}
}
}
int main(void)
{
int s;
struct sockaddr_in addr;
s = socket(PF_INET, SOCK_STREAM, 0);
if (s == -1)
{
perror("socket() failed");
return 1;
}
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(PORT);
addr.sin_family = AF_INET;
if (bind(s, (struct sockaddr*)&addr, sizeof(addr)) == -1)
{
perror("bind() failed");
return 2;
}
if (listen(s, 3) == -1)
{
perror("listen() failed");
return 3;
}
return main_loop(s);
}
Lesezeichen