赞
踩
与多进程很相似,不多赘述,具体内容在多进程服务器的文章中
#include <stdio.h> #include <arpa/inet.h> #include <stdlib.h> #include <pthread.h> #include <sys/socket.h> #include <unistd.h> #include <sys/types.h> #define SERV_PORT 5001 #define BACKLOG 5 void* fun(void *arg); typedef struct //自定义一种数据结构保存每个连接客户端的相关信息 { int fd; struct sockaddr_in addr; //存放ip pthread_t id; //存放线程号 }SockInfo; int main(int argc, char *argv[]) { int rw_fd; int fd; int ret; socklen_t len = sizeof(struct sockaddr); struct sockaddr_in sin = {0}; int i = 0; SockInfo info[32]; for(i = 0; i < sizeof(info)/sizeof(info[0]); i++) info[i].fd = -1; //初始化为-1 //创建socket if((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("socket"); exit(-1); } //初始化并绑定本机的ip和端口 sin.sin_family = AF_INET; sin.sin_port = htons(SERV_PORT); //如果端口号需要输入则转化一下 //int port = atoi(argv[1]); sin.sin_port = htons(port); sin.sin_addr.s_addr = htonl(INADDR_ANY); //避免出现bind error:address already in use的情况,设置端口复用 //出现以上错误的原因是断开连接后需要等待2MSL时间 int flag; setsockopt = (fd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag)); if((bind(fd, (struct sockaddr *)&sin, sizeof(sin))) < 0) { perror("bind"); exit(-1); } //监听socket if(listen(fd, BACKLOG) < 0) { perror("listen"); exit(-1); } while(1) { //这样是为了选出未使用的最小的i,如果不这么做,如果已经连接的客户端又断开了,那他的i就无法 //被使用,通过初始化fd为-1,并在断开的时候再次设置为-1,达到重复利用的目的 for(i = 0; i < sizeof(info)/sizeof(info[0]); i++) { if(info[i].fd == -1) break; } //主进程接收客户端请求 if((info[i].fd = accept(fd, (struct sockaddr *)&info[i].addr, &len)) < 0) { perror("accept"); exit(-1); } //创建子线程用于通信 pthread_create(&info[i].id, NULL, fun, &info[i]); //设置线程分离,线程结束后会自动回收资源 pthread_detach(info[i].id); if(i == 32) //数值跟创建的结构体数组的大小有关 break; } close(fd); //只退出主线程,对子线程没有影响 pthread_exit(NULL); return 0; } void* fun(void *arg) { char ip[64]; char buf[1024]; SockInfo *info = (SockInfo *)arg; //接下来就是通信 while(1) { //打印客户端ip和端口号 printf("Cilent IP: %s, Port: %d\n\n", inet_ntop(AF_INET,&info->addr.sin_addr.s_addr, ip, sizeof(ip)), ntohs(info->addr.sin_port)); int len = read(info->fd, buf, sizeof(buf)); if(len == -1) { perror("read error"); pthread_exit(NULL); } else if(len == 0) { info->fd = -1; printf("客户端已经断开连接\n"); close(info->fd); break; } else { printf("recv client: %s\n",buf); write(info->fd, buf, len); } } return NULL; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。