#include #include #include #include #include #include // 传递连接参数的信息结构体,将客户端的连接信息存储到结构体里面 struct SockInfo{ struct sockaddr_in caddr; int cfd; }; // 可以创建一个结构体数组用于存放客户端的连接信息,数组容量即是可以接受的最大的客户端连接 struct SockInfo infos[512]; void* working(void* arg); int main(int argc, char const *argv[]) { // 1.创建监听的套接字 int fd = socket(AF_INET, SOCK_STREAM, 0); if(fd == -1){ perror("server listen socket create failed"); return -1; } printf("create server socket succesed\n"); // 2.绑定本地的ip地址和port端口号 struct sockaddr_in saddr; saddr.sin_family = AF_INET; saddr.sin_addr.s_addr = INADDR_ANY; saddr.sin_port = htons(9999); int ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)); if(ret == -1){ perror("server listen socket bind host failed"); return -1; } printf("server bind localhost ip and port(sockaddr_in) successed\n"); // 3.设置监听, linux系统中最大监听socket的连接数是128 ret = listen(fd, 128); if(ret == -1){ perror("sever listen failed"); return -1; } printf("server listen successed\n"); // 初始化结构体数组 int max = sizeof(infos)/sizeof(infos[0]); for(int i=0; icaddr, &caddrlen); if(cfd == -1){ perror("connection failed"); //return -1; // 直接返回 or break; // 中断循环,结束客户端的连接,or //continu; // 继续循环,等待客户端连接 } pInfo->cfd = cfd; // 创建子线程 pthread_t pid; pthread_create(&pid, NULL, working, pInfo); pthread_detach(pid); } close(fd); return 0; } void* working(void * arg){ struct SockInfo* pInfo = (struct SockInfo*)arg; // 连接建立成功,打印客户端的ip和port信息 char ip[32]; printf("client IP: %s, Port: %d -- connection successed!\n", inet_ntop(pInfo->caddr.sin_family, &pInfo->caddr.sin_addr.s_addr, ip, sizeof(ip)), ntohs(pInfo->caddr.sin_port)); printf("----------------------------------------------------------------------------------------------------------\n"); int num = 0; // 5.通信 while(1){ // 接收数据 char buff[1024]; int len = recv(pInfo->cfd, buff, sizeof(buff), 0); if(len > 0){ printf("client say: %s\n", buff); memset(buff, 0, sizeof(buff)); sprintf(buff, "hello, client...%d\n", num++); printf("server: %s\n", buff); send(pInfo->cfd, buff, strlen(buff)+1, 0); }else if(len == 0){ printf("client IP: %s, Port: %d -- has disconnect.\n", inet_ntop(pInfo->caddr.sin_family, &pInfo->caddr.sin_addr.s_addr, ip, sizeof(ip)), ntohs(pInfo->caddr.sin_port)); break; }else{ perror("call recv fail."); break; } } // 6.关闭文件描述符 close(pInfo->cfd); pInfo->cfd = -1; // 将pInfo指针指向的SockInfo数组中的SockInfo结构体的文件描述符置为-1,以在后续连接中重新赋值 return NULL; }