【C语言】多线程服务器

时间:2024-07-15 14:20:46
#include <socketwrap.h> #include <arpa/inet.h> #include <pthread.h> #include <strings.h> #include <string.h> #include <ctype.h> #include <arpa/inet.h> #include <arpa/inet.h> #include <sys/types.h> #include <unistd.h> typedef struct info { int cfd; // 若为-1表示可用, 大于0表示已被占用 int idx; pthread_t thread; // 由pthread_create 返回 struct sockaddr_in client; // 由accept 返回 } INFO; INFO thInfo[1024]; void initThreadArr() { for (int i = 0; i < 1024; i++) { bzero(&thInfo[i],sizeof(thInfo[i])); thInfo[i].cfd = -1; } } int findIndex() { int i; for (i = 0; i < 1024; i++) { if (thInfo[i].cfd == -1) { return i; } } if (i == 1024) { return -1; } } void *threadFunc(void *arg) { INFO *curthread = (INFO *)arg; char sIP[16]; printf("current thread id [%ld],arr index is [%d],cfd is [%d],client ip is [%s:%d]\n", pthread_self(), curthread->idx, curthread->cfd, inet_ntop(AF_INET, &curthread->client.sin_addr.s_addr, sIP, sizeof(sIP)), ntohs(curthread->client.sin_port)); char buff[64]; while (1) { memset(buff, 0x00, sizeof(buff)); int n = Read(curthread->cfd, buff, sizeof(buff)); if (n == 0) { bzero(&thInfo[curthread->idx],sizeof(thInfo[curthread->idx])); thInfo[thInfo->idx].cfd = -1; return 0; } else if (n < 0) { bzero(&thInfo[curthread->idx],sizeof(thInfo[curthread->idx])); thInfo[thInfo->idx].cfd = -1; perror("child read error"); return 0; } printf("child thread [%ld] recv data from [%s:%d]:[%s]\n", pthread_self(), inet_ntop(AF_INET, &curthread->client.sin_addr.s_addr, sIP, sizeof(sIP)), ntohs(curthread->client.sin_port), buff); for (int i = 0; i < n; i++) { buff[i] = toupper(buff[i]); } n = Write(curthread->cfd, buff, n); if (n <= 0) { bzero(&thInfo[curthread->idx],sizeof(thInfo[curthread->idx])); thInfo[thInfo->idx].cfd = -1; perror("child write error"); return 0; } } } int main() { initThreadArr(); int sfd = Socket(AF_INET, SOCK_STREAM, 0); // 设置端口复用 int opt = 1; setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int)); struct sockaddr_in soaddr; bzero(&soaddr, sizeof(soaddr)); soaddr.sin_family = AF_INET; soaddr.sin_port = htons(9999); soaddr.sin_addr.s_addr = htonl(INADDR_ANY); Bind(sfd, (struct sockaddr *)&soaddr, sizeof(soaddr)); // 监听-listen Listen(sfd, 128); struct sockaddr_in clientsocket; socklen_t clilen; int cfd; int index; int ret; while (1) { index = -1; clilen = sizeof(clientsocket); bzero(&clientsocket, clilen); cfd = Accept(sfd, (struct sockaddr *)&clientsocket, &clilen); // 从线程数组中找一个可以用的 index = findIndex(); thInfo[index].idx = index; thInfo[index].client = clientsocket; thInfo[index].cfd = cfd; // 创建线程 ret = pthread_create(&thInfo[index].thread, NULL, threadFunc, &thInfo[index]); if (ret != 0) { printf("create thread error:[%s]\n", strerror(ret)); exit(-1); } // 设置子线程为分离属性 pthread_detach(thInfo[index].thread); } Close(sfd); return 0; }