云计算百科
云计算领域专业知识百科平台

tcp并发服务器,多进程、多线程

1.进程

#include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> #include <string.h> #include <unistd.h> #include <stdlib.h> #include <signal.h>

#define SER_PORT 6666 #define SER_IP  "192.168.124.33"   //"0.0.0.0"

int deal_cli_msg(int newfd,struct sockaddr_in cin); void signal_handle(int signum);

int main(int argc, const char *argv[]) {     //创建流式套接字     int sfd = socket(AF_INET, SOCK_STREAM, 0);     if(sfd < 0)     {         fprintf(stderr, "__%d__ ", __LINE__);         perror("socket");         return -1;     }     printf("socket success __%d__\\n", __LINE__);

    //允许端口快速重用                                                                                       int reuse = 1;     if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)     {         fprintf(stderr, "__%d__ ", __LINE__);         perror("setsockopt");         return -1;     }     printf("reuseaddr success __%d__\\n", __LINE__);

    //若从命令行传入端口号,则使用传入的端口号,没有传入则使用宏定义的端口号     int port =  argc>=2?atoi(argv[1]):SER_PORT;

    //填充服务器的地址信息结构体,给bind函数使用     //真实的地址信息结构体根据地址族指定 AF_INET: man 7 ip     struct sockaddr_in sin;     sin.sin_family      = AF_INET;              //必须填AF_INET     sin.sin_port        = htons(port);          //端口号的网络字节序,1024~49151     sin.sin_addr.s_addr = inet_addr(SER_IP);    //本机IP的网络字节序,ifconfig查看本机IP                                                 //127.0.0.1:本地换回IP,只能做本机通信的IP                                                 //0.0.0.0 : 代表运行环境中所有可用IP

    //绑定服务器自身的地址信息     if(bind(sfd, (struct sockaddr*)&sin, sizeof(sin)) < 0)     {         fprintf(stderr, "__%d__ ", __LINE__);         perror("bind");         return -1;     }     printf("bind success __%d__\\n", __LINE__);

    //将套接字设置为被动监听状态     if(listen(sfd, 128) < 0)     {         fprintf(stderr, "__%d__ ", __LINE__);         perror("listen");         return -1;     }     printf("listen success __%d__\\n", __LINE__);

    //阻塞等待客户端连接成功,从已完成连接的队列头中获取一个客户端信息,     //生成一个新的文件描述符,这个新的文件描述符才是与客户端通信用的文件描述符     struct sockaddr_in cin;     //存储获取到的客户端的地址信息     socklen_t addrlen = sizeof(cin);

    int newfd=-1;     pid_t pid=0;     signal(SIGCHLD, signal_handle);     while(1)     {         newfd = accept(sfd, (struct sockaddr*)&cin, &addrlen);         if(newfd < 0)         {             fprintf(stderr, "__%d__ ", __LINE__);             perror("accpet");             return -1;         }         printf("client connect success, [%s:%d] newfd = %d __%d__\\n", \\                 inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), newfd, __LINE__);

        pid=fork();         if(pid==0)         {             close(sfd);             deal_cli_msg(newfd,cin);             close(newfd);             exit(0);         }         close(newfd);     }     //关闭     close(sfd);

    return 0; }

int deal_cli_msg(int newfd,struct sockaddr_in cin) {     char buf[128] = "";     ssize_t res = 0;     while(1)     {         bzero(buf, sizeof(buf));    //memset(buf, 0, sizeof(buf));         //收         res = recv(newfd, buf, sizeof(buf), 0);         if(res < 0)         {             fprintf(stderr, "__%d__ ", __LINE__);             perror("recv");             return -1;         }         else if(0 == res)         {             printf("client [%s:%d] offline  __%d__\\n",\\                     inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), __LINE__);             break;         }

        printf("[%s:%d] newfd=%d : %s\\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), newfd, buf);

        //发         strcat(buf, ">_<");         if(send(newfd, buf, sizeof(buf), 0) < 0)         {             fprintf(stderr, "__%d__ ", __LINE__);             perror("send");             return -1;         }         printf("send success __%d__\\n", __LINE__);     } }

void signal_handle(int signum) {     int status;          if(signum == SIGCHLD){                  int ret = wait( &status);         if(ret < 0 ){             perror("wait error");             return ;         }     }          printf("fataher found subprocess exit %d\\n",  (signed char) ((status >>8)&0xFF )  ); }

1.线程

#include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> #include <string.h> #include <unistd.h> #include <stdlib.h> #include <pthread.h>

#define SER_PORT 6666 #define SER_IP  "192.168.124.33"   //"0.0.0.0"

struct thread_data {     pthread_t tid;     int newfd;     struct sockaddr_in cin; }; void* thead_handle_fun(void* arg);

int main(int argc, const char *argv[]) {     //创建流式套接字     int sfd = socket(AF_INET, SOCK_STREAM, 0);     if(sfd < 0)     {         fprintf(stderr, "__%d__ ", __LINE__);         perror("socket");         return -1;     }     printf("socket success __%d__\\n", __LINE__);

    //允许端口快速重用                                                                                       int reuse = 1;     if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)     {         fprintf(stderr, "__%d__ ", __LINE__);         perror("setsockopt");         return -1;     }     printf("reuseaddr success __%d__\\n", __LINE__);

    //若从命令行传入端口号,则使用传入的端口号,没有传入则使用宏定义的端口号     int port =  argc>=2?atoi(argv[1]):SER_PORT;

    //填充服务器的地址信息结构体,给bind函数使用     //真实的地址信息结构体根据地址族指定 AF_INET: man 7 ip     struct sockaddr_in sin;     sin.sin_family      = AF_INET;              //必须填AF_INET     sin.sin_port        = htons(port);          //端口号的网络字节序,1024~49151     sin.sin_addr.s_addr = inet_addr(SER_IP);    //本机IP的网络字节序,ifconfig查看本机IP                                                 //127.0.0.1:本地换回IP,只能做本机通信的IP                                                 //0.0.0.0 : 代表运行环境中所有可用IP

    //绑定服务器自身的地址信息     if(bind(sfd, (struct sockaddr*)&sin, sizeof(sin)) < 0)     {         fprintf(stderr, "__%d__ ", __LINE__);         perror("bind");         return -1;     }     printf("bind success __%d__\\n", __LINE__);

    //将套接字设置为被动监听状态     if(listen(sfd, 128) < 0)     {         fprintf(stderr, "__%d__ ", __LINE__);         perror("listen");         return -1;     }     printf("listen success __%d__\\n", __LINE__);

    //阻塞等待客户端连接成功,从已完成连接的队列头中获取一个客户端信息,     //生成一个新的文件描述符,这个新的文件描述符才是与客户端通信用的文件描述符     struct sockaddr_in cin;     //存储获取到的客户端的地址信息     socklen_t addrlen = sizeof(cin);

    struct thread_data* pdata=malloc(sizeof(*pdata));     memset(pdata,0,sizeof(*pdata));     while(1)     {         int newfd = accept(sfd, (struct sockaddr*)&cin, &addrlen);         if(newfd < 0)         {             fprintf(stderr, "__%d__ ", __LINE__);             perror("accpet");             return -1;         }         printf("client connect success, [%s:%d] newfd = %d __%d__\\n", \\                 inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), newfd, __LINE__);                  pdata->newfd=newfd;         pdata->cin=cin;                  int ret = pthread_create(&pdata->tid, NULL, thead_handle_fun  ,pdata );         if(ret <0){             perror("create thread err");             return -34;         }         pthread_detach( pdata->tid);

             }     close(sfd);

    return 0; }

void* thead_handle_fun(void* arg) {     struct thread_data *p = arg;     int newfd=p->newfd;     struct sockaddr_in cin=p->cin;     char buf[128] = "";     ssize_t res = 0;     while(1)     {         bzero(buf, sizeof(buf));    //memset(buf, 0, sizeof(buf));         //收         res = recv(newfd, buf, sizeof(buf), 0);         if(res < 0)         {             fprintf(stderr, "__%d__ ", __LINE__);             perror("recv");             return -1;         }         else if(0 == res)         {             printf("client [%s:%d] offline  __%d__\\n",\\                     inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), __LINE__);             break;         }

        printf("[%s:%d] newfd=%d : %s\\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), newfd, buf);

        //发         strcat(buf, ">_<");         if(send(newfd, buf, sizeof(buf), 0) < 0)         {             fprintf(stderr, "__%d__ ", __LINE__);             perror("send");             return -1;         }         printf("send success __%d__\\n", __LINE__);     }     close(newfd); }

赞(0)
未经允许不得转载:网硕互联帮助中心 » tcp并发服务器,多进程、多线程
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!