功能:监听本地8888端口,接收到客户端连接请求后创建线程单独处理与客户端的交互,支持同时与多个客户端交互。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>#define PORT 8888void *deal_client(void *args)
{int fd;int i;unsigned char recv_buff[1024] = {0};int read_len = 0;int send_len = 0;unsigned char *send_data = "hello,this is a tcp server\n";fd = (int) *(int *) args;printf("fd %d\n", fd);if (fd < 0){printf("socket err\n");return NULL;}while (1){memset(recv_buff, 0x00, sizeof (recv_buff));read_len = recv(fd, recv_buff, sizeof (recv_buff), 0);if (read_len < 0){printf("recv err\n");close(fd);fd = -1;return NULL;} else if (read_len == 0){printf("close \n");close(fd);fd = -1;return NULL;}printf("recv data: %s\n", recv_buff);// for (i = 0; i < read_len; i++)// {// printf("%02x ", recv_buff[i]);// }// printf("\n");send_len = send(fd, send_data, strlen(send_data), 0);if (send_len <= 0){printf("send err\n");close(fd);fd = -1;return NULL;}}
}int main()
{//创建套接字int socket_fd = socket(AF_INET, SOCK_STREAM, 0);if (socket_fd < 0){printf("socket err\n");return -1;}printf("socket create success sfd=%d\n", socket_fd);//设置端口重用int resue = 1;if (setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &resue, sizeof (resue)) < 0){printf("setsockopt SO_REUSEADDR err\n");return -1;}//填充服务器的地址信息结构体struct sockaddr_in sin;sin.sin_family = AF_INET;sin.sin_port = htons(PORT);sin.sin_addr.s_addr = inet_addr("0.0.0.0");//绑定端口号if (bind(socket_fd, (struct sockaddr*) &sin, sizeof (sin)) < 0){printf("bind err\n");return -1;}printf("bind success\n");//监听端口号if (listen(socket_fd, 5) == -1){printf("listen err\n");return -1;}printf("listen success\n");while (1){struct sockaddr_in cin; //存储连接成功的客户端地址socklen_t addrlen = sizeof (cin);int socket_cli = -1;socket_cli = accept(socket_fd, (struct sockaddr*) &cin, &addrlen);if (socket_cli < 0){printf("accept err\n");continue;}printf("socket_cli %d\n", socket_cli);pthread_t tid = -1;pthread_create(&tid, NULL, deal_client, &socket_cli);usleep(1000); //注意这里必须sleep一下,不然参数传递不过去}
}