基于TCP协议用多线程实现并发服务器,实现思路、算法和demo
来源:互联网 发布:麒麟970 知乎 编辑:程序博客网 时间:2024/06/11 10:56
基本的思路:用主线程负责client的连接, 然后当有客户端来连接的时候,创建子进程。在子进程里面实现数据的接收。
1.myhead.h
先把一些要用的API的头文件都写进来。
- #ifndef _MYHEAD_H_
- #define _MYHEAD_H_
-
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <string.h>
- #include <unistd.h>
- #include <sys/wait.h>
- #include <pthread.h>
-
- #define MYPORT 6667 //1024以下的是保留的端口号,用大于1024的;
-
-
- #endif
2.server.c
- #include "myhead.h"
-
- void *read_msg(void *argc);
-
- int main()
- {
- int ret = 0;
- int socketfd = 0;
- int clientfd = 0;
-
- pid_t pid = 0;
- pthread_t th = 0;
-
-
- struct sockaddr_in sock_server = {0};
- struct sockaddr_in sock_client = {0};
-
- socklen_t len = sizeof(struct sockaddr);
-
-
- socketfd = socket(AF_INET,SOCK_STREAM,0);
- if(socketfd == -1)
- {
- perror("socket");
- return -1;
- }
- printf("socket success...\n");
-
-
- sock_server.sin_family = AF_INET;
- sock_server.sin_port = htons(MYPORT);
-
- sock_server.sin_addr.s_addr = htonl(INADDR_ANY);
-
- ret = bind(socketfd,(struct sockaddr *)&sock_server,sizeof(struct sockaddr));
- if(ret == -1)
- {
- perror("bind");
- return -1;
- }
- printf("bind success..\n");
-
-
- ret = listen(socketfd,10);
- if(ret == -1)
- {
- perror("listen");
- return -1;
- }
- printf("listen success...\n");
-
-
-
-
-
-
-
-
-
-
- while(1)
- {
- clientfd = accept(socketfd,(struct sockaddr *)&sock_client,&len);
- if(clientfd == -1)
- {
- perror("accept");
- return -1;
- }
- printf("accept success... clientfd = %d\n",clientfd);
- ret = pthread_create(&th,NULL,read_msg,&clientfd);
- if(ret != 0)
- {
- perror("pthread_create");
- return -1;
- }
- }
- close(socketfd);
-
- return 0;
- }
-
- void *read_msg(void *argc)
- {
-
-
-
- int fd = *((int *)argc);
- printf("fd = %d\n",fd);
-
- char recvbuff[20] = {0};
- int recvcnt = 0;
-
- while(1)
- {
- bzero(recvbuff,sizeof(recvbuff));
- recvcnt = read(fd,recvbuff,sizeof(recvbuff));
- if(recvcnt == -1)
- {
- perror("recv");
- return NULL;
- }
- else if(recvcnt == 0)
- {
- printf("The Client is closed!\n");
- break;
- }
- else
- {
- printf("Recv from Client %d bytes,data:%s\n",recvcnt,recvbuff);
- }
- if(strcmp(recvbuff,"end") == 0)
- {
- break;
- }
- }
- close(fd);
-
- return NULL;
- }
3.client.c
- #include "myhead.h"
-
-
- int main(int argc,char **argv)
- {
-
- if(argc != 2)
- {
- perror("argc");
- return -1;
- }
- int socketfd = 0;
- int ret = 0;
-
- struct sockaddr_in sock_server = {0};
-
- socketfd = socket(AF_INET,SOCK_STREAM,0);
- if(-1 == socketfd)
- {
- perror("socket");
- return -1;
- }
- printf("socket success...\n");
-
-
- sock_server.sin_family = AF_INET;
- sock_server.sin_port = htons(MYPORT);
-
- sock_server.sin_addr.s_addr = inet_addr(argv[1]);
-
- ret = connect(socketfd,(struct sockaddr *)&sock_server,sizeof(struct sockaddr));
- if(ret == -1)
- {
- perror("connect");
- return -1;
- }
-
- char sendbuff[20] = {0};
- int sendcnt = 0;
-
- while(1)
- {
-
- printf("Please input a string:\n");
- scanf("%s",sendbuff);
-
-
-
- sendcnt = write(socketfd,sendbuff,strlen(sendbuff));
- if(sendcnt == -1)
- {
- perror("send");
- return -1;
- }
- else
- {
- printf("Send to Server %d bytes,data:%s\n",sendcnt,sendbuff);
- }
-
- if(strcmp(sendbuff,"end") == 0)
- {
- close(socketfd);
- break;
- }
- }
-
- return 0;
- }
分别编译服务器和客户端程序: gcc server.c -o server gcc client.c -o client 然后,先运行服务器./server,再运行客户端./client,客户端发消息给服务器,服务器回复,实现基本的一收一发的功能。