近偶尔有时间,研究了下Socket的使用,虽然不简单,不过还是挺有意思,刚好咱们带头大哥需要我们发檄文,也罢,那来一篇,废话不多说,直接入正题
struct sockaddr_in server_addr;
pthread_mutex_t mut;
struct kevent events[10];
//IP地址、端口和协议族
server_addr.sin_len = sizeof(struct sockaddr_in);
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(SERVER_PORT);
server_addr.sin_addr.s_addr = inet_addr(ipAddress);
bzero(&(server_addr.sin_zero),8);
//创建socket
int server_sock_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server_sock_fd == -1) {
perror("socket error");
return NULL;
}
int on=1;
if((setsockopt(server_sock_fd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)))<0)
{
perror("setsockopt failed");
exit(EXIT_FAILURE);
}
//绑定socket
int bind_result = bind(server_sock_fd, (struct sockaddr *)&server_addr, sizeof(server_addr));
if (bind_result == -1) {
perror("bind error");
return NULL;
}
//监听
if (listen(server_sock_fd, BACKLOG) == -1) {
perror("listen error");
return NULL;
}
struct timespec timeout = {10,0};
//kqueue
int kq = kqueue();
if (kq == -1) {
perror("创建kqueue出错! ");
exit(1);
}
struct kevent event_change;
EV_SET(&event_change, STDIN_FILENO, EVFILT_READ, EV_ADD, 0, 0, NULL);
kevent(kq, &event_change, 1, NULL, 0, NULL);
EV_SET(&event_change, server_sock_fd, EVFILT_READ, EV_ADD, 0, 0, NULL);
kevent(kq, &event_change, 1, NULL, 0, NULL);
while (1) {
int ret = kevent(kq, NULL, 0, events, 10, &timeout);
if (ret < 0) {
printf("kevent 出错! ");
continue;
}else if(ret == 0){
printf("kenvent 超时! ");
continue;
}else{
//ret > 0 返回事件放在events中
for (int i = 0; i < ret; i++) {
struct kevent current_event = events[i];
//kevent中的ident是文件描述符
if (current_event.ident == STDIN_FILENO) {
//标准输入
bzero(input_msg, BUFFER_SIZE);
fgets(input_msg, BUFFER_SIZE, stdin);
//输入 ".quit" 则退出服务器
if (strcmp(input_msg, QUIT_CMD) == 0) {
exit(0);
}
for (int i=0; i<CONCURRENT_MAX; i++) {
if (client_fds[i]!=0) {
send(client_fds[i], input_msg, BUFFER_SIZE, 0);
}
}
}else if(current_event.ident == server_sock_fd){
//有新的连接请求
struct sockaddr_in client_address;
socklen_t address_len;
int client_socket_fd = accept(server_sock_fd, (struct sockaddr *)&client_address, &address_len);
if (client_socket_fd > 0) {
int index = -1;
for (int i = 0; i < CONCURRENT_MAX; i++) {
if (client_fds[i] == 0) {
index = i;
client_fds[i] = client_socket_fd;
break;
}
}
if (index >= 0) {
EV_SET(&event_change, client_socket_fd, EVFILT_READ, EV_ADD, 0, 0, NULL);
kevent(kq, &event_change, 1, NULL, 0, NULL);
printf("新客户端(fd = %d)加入成功 %s:%d ",client_socket_fd,inet_ntoa(client_address.sin_addr),ntohs(client_address.sin_port));
/*客户端赋值*/
strcpy(client.ipAddress, inet_ntoa(client_address.sin_addr));
client.client_port = ntohs(client_address.sin_port);
client.client_ID = client_socket_fd;
/*收集客户端信息并且存储到列表中*/
//                            if (AddClient(client, &clientList) == false) {
//                                fprintf(stderr, "Problem allcating memory ");
//                                break;
//                            }
//                            if(ListIsFull(&clientList))
//                            {
//                                puts("The list is now full. ");
//                                break;
//                            }
//                            if(ListIsEmpty(&clientList))
//                            {
//                                printf("NO client Connection");
//                            }else
//                            {
//                                Traverse(&clientList, showClients);
//                            }
//                            printf("在线客户端人数:%d ", ListClientCount(&clientList));
if(!QueueIsFull(&line))
{
client.client_ID = client_socket_fd;
client.client_port = ntohs(client_address.sin_port);
strcpy(client.ipAddress, inet_ntoa(client_address.sin_addr));
EnQueue(client, &line); //将客户端添加到队列中
char msg[250];
char wellcome[250];
sprintf(msg,"新客户端(fd = %d) 加入成功 %s:%d",client_socket_fd,inet_ntoa(client_address.sin_addr),ntohs(client_address.sin_port));
sprintf(wellcome, "WellComm To NB Socket Server System your fd is %d addr is %s and port is %d",client_socket_fd,inet_ntoa(client_address.sin_addr),ntohs(client_address.sin_port));
//给所有客户端发送消息,除了刚刚连接上的客户端之外
for(int i=0; i<QueueItemCount(&line); i++)
{
if(index != i)
{
send(client_fds[i], msg, BUFFER_SIZE, 0);
}else
{
send(client_fds[i], wellcome, BUFFER_SIZE, 0);
}
}
}
}else{
bzero(input_msg, BUFFER_SIZE);
strcpy(input_msg, "服务器加入的客户端数达到大值,无法加入! ");
send(client_socket_fd, input_msg, BUFFER_SIZE, 0);
printf("客户端连接数达到大值,新客户端加入失败 %s:%d ",inet_ntoa(client_address.sin_addr),ntohs(client_address.sin_port));
}
}
}else{
//处理某个客户端过来的消息