#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<pthread.h>
#include<unistd.h>
#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<errno.h>
#define SERVER_PORT 8888
typedef struct
{
int c_fd;
char ip[16];
}clinet;
#define MAX_CLINET 100
clinet g_clinet[MAX_CLINET];
pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
void broadcast(int fd, void * msg, int len)
{
write(STDOUT_FILENO, msg , len);
pthread_mutex_lock(&m);
int i =0;
for(;i < MAX_CLINET; i++)
{
if(g_clinet[i].c_fd != 0 && g_clinet[i].c_fd != fd)
{
write(g_clinet[i].c_fd, msg, len);
}
}
pthread_mutex_unlock(&m);
}
void * func(void *arg)
{
clinet *parg = arg;
char ip[16] = {0};
pthread_mutex_lock(&m);
int c_fd = parg->c_fd;
strncpy(ip, parg->ip, sizeof(ip));
pthread_mutex_unlock(&m);
char msg[1024];
int n = sprintf(msg, "Welcome %s join us\n", ip);
int ip_len = sprintf(msg, " %s said: ", ip);
broadcast(0 ,msg , n); //对所有客户端广播
for(;;)
{
int len = read(c_fd, msg+ip_len, sizeof(msg) - ip_len);
if(len < 0)
break;
if(msg[ip_len] == 'q' && isspace(msg[ip_len+1]))
break;
broadcast(c_fd ,msg , len+ip_len); //对所有客户端广播
}
close(c_fd);
pthread_mutex_lock(&m);
parg->c_fd = 0;
pthread_mutex_unlock(&m);
n = sprintf(msg, "%s leaved\n", ip);
broadcast(0 ,msg , n); //对所有客户端广播
}
int main(int argc,char* argv[])
{
int s_fd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in si;
memset(&si, 0 , sizeof(si));
si.sin_family = AF_INET;
si.sin_addr.s_addr = htonl(INADDR_ANY);
si.sin_port = htons(SERVER_PORT);
if(bind(s_fd, (struct sockaddr *)&si, sizeof(si)) < 0)
{
perror("bind failed.\n");
return -1;
}
listen(s_fd, 10);
for(;;)
{
socklen_t len = sizeof(si);
int c_fd = accept(s_fd, (struct sockaddr *)&si, &len);
if(c_fd < 0)
{
continue;
}
int i = 0;
pthread_mutex_lock(&m);
for(i = 0; i < MAX_CLINET && g_clinet[i].c_fd != 0; i++){}
if(i == MAX_CLINET)
{
write(c_fd, "full!\n",6);
close(c_fd);
}
else
{
g_clinet[i].c_fd = c_fd;
inet_ntop(AF_INET, &si.sin_addr, g_clinet[i].ip, sizeof(g_clinet[i].ip));
pthread_t id;
pthread_create(&id, NULL , func, &g_clinet[i]);
}
pthread_mutex_unlock(&m);
}
}