linux 多线程聊天服务器
2016-05-26 22:50
435 查看
自己写的linux多线程聊天服务器,可以实现并发,通过链表添加人数。
#include <asm-generic/socket.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <sys/socket.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <pthread.h> #include <string.h> typedef struct { int sockfd; char name[32]; } Client; typedef struct _node { Client c; struct _node* prev; struct _node* next; } Node; Node* head = NULL; void list_init() { head = malloc(sizeof(Node)); head->prev = head; head->next = head; } void list_insert(Client* ps) { Node* p = malloc(sizeof(Node)); p->c = *ps; p->prev = head; p->next = head->next; head->next->prev = p; head->next = p; } void list_erase(int sockfd) { Node* p = head->next; while (p != head) { if (sockfd == p->c.sockfd) { p->prev->next = p->next; p->next->prev = p->prev; free(p); return; } p = p->next; } } void list_tracvel() { Node* p = head->next; while (p != head) { printf("sockfd=%d\n", p->c.sockfd); p = p->next; } } int list_size() { int cnt = 0; Node* p = head->next; while (p != head) { ++cnt; p = p->next; } return cnt; } void send_all(char* msg) { Node* p = head->next; while (p != head) { send(p->c.sockfd, msg, strlen(msg), 0); p = p->next; } } void * thread_handler(void * p) { int clientfd = *(int *) p; //获取地址信息 struct sockaddr_in c_addr; socklen_t c_len = 16; getpeername(clientfd, (struct sockaddr*) &c_addr, &c_len); printf("a client %s:%d connected\n", inet_ntoa(c_addr.sin_addr), ntohs(c_addr.sin_port)); char wel_msg[128] = "welcome to lizhu's chat room!\r\n"; send(clientfd, wel_msg, strlen(wel_msg), 0); sprintf(wel_msg,"welcame to lizhu's char room! current on line num%d\n",(list_size()+1)); char prompt_msg[128] = "please input you name:"; send(clientfd, prompt_msg, strlen(prompt_msg), 0); char name[32] = { 0 }; recv(clientfd, name, sizeof(name), 0); char *q = strstr(name, "\r\n"); if (q) *q = "\0"; Client c; c.sockfd = clientfd; strcpy(c.name, name); char online_msg[128] = { 0 }; //发送上信息 sprintf(online_msg, "%s is online!\r\n", c.name); send_all(online_msg); list_insert(&c); //链表添加 while (1) { char recv_msg[128] = { '\0' }; int size = recv(clientfd, recv_msg, sizeof(recv_msg), 0); if (size <= 2 || strncasecmp("quit", recv_msg, 4) == 0) break; send_all(recv_msg); printf("a client %s:%d exit \n", inet_ntoa(c_addr.sin_addr), ntohs(c_addr.sin_port)); char wel_msg[128] = "welcome back to lizhu's chat room!\r\n"; send(clientfd, wel_msg, strlen(wel_msg), 0); list_erase(clientfd); //链表添加 char offline_msg[128] = { 0 }; //发送上信息 sprintf(offline_msg, "%s is online!\r\n", c.name); send_all(offline_msg); close(clientfd); return NULL; } } void start() { int sockfd = socket(AF_INET, SOCK_STREAM, 0); //PF_INET if (-1 == sockfd) { perror("socket"); exit(1); } int opt = 1; //1代表可以重用 解决服务器端口占用 setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, 4); //4代表opt的大小 struct sockaddr_in ser_addr; ser_addr.sin_family = AF_INET; ser_addr.sin_addr.s_addr = INADDR_ANY; //inet_addr("127.0.0.1"); ser_addr.sin_port = htons(3000); int ret = bind(sockfd, (struct sockaddr*) &ser_addr, 16); if (-1 == ret) { perror("bind"); exit(1); } ret = listen(sockfd, 20); if (-1 == ret) { perror("listen"); exit(1); } printf("lizhu server is ready\n"); while (1) { int newfd = accept(sockfd, NULL, NULL); if (-1 == newfd) { perror("accept"); continue; } printf("a client connected\n"); pthread_t tid; int ret = pthread_create(&tid, NULL, thread_handler, &newfd); if (ret) { perror("pthread_create\n"); } } close(sockfd); } int main(int agc, char *agv[]) { list_init(); start(); return 0; }
相关文章推荐
- 小心服务器内存居高不下的元凶--WebAPI服务
- Python3写爬虫(四)多线程实现数据爬取
- 如何组织构建多文件 C 语言程序(二)
- 运维入门
- [C/C++]反转链表
- [原创]java局域网聊天系统
- 如何写好 C main 函数
- 利用开源软件打造自己的全功能远程工具
- Linux5.9无人值守安装
- 数据中心和云未来的十二大趋势
- 用vsftp快速搭建ftp服务器
- Linux快速构建apache web服务器
- 服务器监控策略浅谈
- 如何降低服务器采购成本 原理分析
- 建议的服务器分区办法
- 服务器托管六大优势分析
- Erlang实现的一个Web服务器代码实例
- 服务器技术全面解析
- C#实现多线程的同步方法实例分析