首页 > 代码库 > c网络编程(server服务器端,linux)
c网络编程(server服务器端,linux)
多进程
1 #include "network.h" 2 3 void do_service(int peerfd) 4 { 5 char recvbuf[1024] = {0}; 6 int ret; 7 while(1) 8 { 9 ret = readline(peerfd, recvbuf, 1024);10 if(ret == 0)11 {12 close(peerfd);13 exit(EXIT_SUCCESS);14 }15 //模拟数据处理过程16 printf("recv data: %s", recvbuf);17 writen(peerfd, recvbuf, strlen(recvbuf));18 }19 }20 21 void handler(int sig)22 {23 while(waitpid(-1, NULL, WNOHANG) > 0)24 ;25 return ;26 }27 28 29 int get_listen_fd();30 31 int main(int argc, const char *argv[])32 {33 if(signal(SIGPIPE, SIG_IGN) == SIG_ERR)34 ERR_EXIT("signal");35 if(signal(SIGCHLD, handler) == SIG_ERR)36 ERR_EXIT("signal");37 38 int listenfd = get_listen_fd();39 40 41 while(1)42 {43 struct sockaddr_in peeraddr;44 memset(&peeraddr, 0, sizeof(peeraddr));45 socklen_t len = sizeof peeraddr;46 int peerfd = accept(listenfd, (struct sockaddr *)&peeraddr, &len);47 if(peerfd == -1)48 ERR_EXIT("accpet");49 pid_t pid;50 if((pid = fork()) < 0)51 ERR_EXIT("fork");52 else if(pid == 0)53 {54 close(listenfd); //子进程必须关闭listenfd55 do_service(peerfd);56 exit(EXIT_SUCCESS);57 }58 59 close(peerfd); //这里必须关闭peerfd,否则导致资源耗尽60 }61 close(listenfd);62 return 0;63 }64 65 66 67 int get_listen_fd()68 {69 //创建socket70 int listenfd = socket(PF_INET, SOCK_STREAM, 0);71 if(listenfd == -1)72 ERR_EXIT("socket");73 74 75 //设置端口复用76 int on = 1;77 if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)78 ERR_EXIT("setsockopt");79 80 struct sockaddr_in servaddr;81 servaddr.sin_family = AF_INET;82 servaddr.sin_port = htons(8989);83 servaddr.sin_addr.s_addr = htonl(INADDR_ANY);84 //bind端口85 if(bind(listenfd, (struct sockaddr*)&servaddr, sizeof servaddr) < 0)86 ERR_EXIT("bind"); 87 88 //listen端口89 if(listen(listenfd, SOMAXCONN) < 0)90 ERR_EXIT("listen");91 92 return listenfd;93 }
多线程
1 #include "network.h" 2 #include <pthread.h> 3 4 5 6 void do_service(int peerfd); 7 int get_listen_fd(); 8 void *thread_func(void *arg); 9 10 int main(int argc, const char *argv[])11 {12 if(signal(SIGPIPE, SIG_IGN) == SIG_ERR)13 ERR_EXIT("signal");14 15 int listenfd = get_listen_fd();16 17 while(1)18 {19 int peerfd = accept(listenfd, NULL, NULL);20 if(peerfd == -1)21 ERR_EXIT("accpet");22 //每接受一个请求,就创建一个新的线程23 24 int *pfd = (int *)malloc(sizeof(int));25 if(pfd == NULL)26 ERR_EXIT("malloc");27 *pfd = peerfd;28 pthread_t tid;29 if(pthread_create(&tid, NULL, thread_func, pfd))30 {31 free(pfd); //确保内存不被泄露32 }33 34 }35 close(listenfd);36 return 0;37 }38 39 void *thread_func(void *arg)40 {41 int *pfd = (int *)arg;42 int peerfd = *pfd;43 free(pfd);44 45 pthread_detach(pthread_self()); //把自己设置为分离状态46 47 do_service(peerfd);48 close(peerfd);49 }50 51 52 53 54 int get_listen_fd()55 {56 //创建socket57 int listenfd = socket(PF_INET, SOCK_STREAM, 0);58 if(listenfd == -1)59 ERR_EXIT("socket");60 61 62 //设置端口复用63 int on = 1;64 if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)65 ERR_EXIT("setsockopt");66 67 struct sockaddr_in servaddr;68 servaddr.sin_family = AF_INET;69 servaddr.sin_port = htons(8989);70 servaddr.sin_addr.s_addr = htonl(INADDR_ANY);71 //bind端口72 if(bind(listenfd, (struct sockaddr*)&servaddr, sizeof servaddr) < 0)73 ERR_EXIT("bind"); 74 75 //listen端口76 if(listen(listenfd, SOMAXCONN) < 0)77 ERR_EXIT("listen");78 79 return listenfd;80 }81 82 83 void do_service(int peerfd)84 {85 char recvbuf[1024] = {0};86 int ret;87 while(1)88 {89 ret = readline(peerfd, recvbuf, 1024);90 if(ret == 0)91 {92 close(peerfd);93 exit(EXIT_SUCCESS);94 }95 //模拟数据处理过程96 printf("recv data: %s", recvbuf);97 writen(peerfd, recvbuf, strlen(recvbuf));98 }99 }
头文件
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <unistd.h> 5 #include <signal.h> 6 #include <errno.h> 7 #include <sys/types.h> 8 #include <sys/socket.h> 9 #include <netinet/in.h>10 #include <arpa/inet.h>11 12 #define ERR_EXIT(m) 13 do { 14 perror(m);15 exit(EXIT_FAILURE);16 }while(0)17 18 19 ssize_t readn(int fd, void *usrbuf, size_t n);20 ssize_t writen(int fd, void *usrbuf, size_t n);21 ssize_t recv_peek(int sockfd, void *usrbuf, size_t n);22 ssize_t readline(int sockfd, void *usrbuf, size_t maxline);
1 #include "network.h" 2 3 4 ssize_t readn(int fd, void *usrbuf, size_t n) 5 { 6 size_t nleft = n; //表示还需要读取的字节数 7 ssize_t nread; 8 char *bufp = usrbuf; //控制read函数存放的位置 9 10 while(nleft > 0) 11 { 12 if((nread = read(fd, bufp, nleft)) == -1) 13 { 14 if(errno == EINTR) //interupt 15 nread = 0; //continue; 中断需要再次读取 16 else 17 return -1; // ERROR 18 }else if(nread == 0) // EOF 19 break; 20 21 nleft -= nread; 22 bufp += nread; 23 } 24 return (n - nleft); 25 } 26 27 ssize_t writen(int fd, void *usrbuf, size_t n) 28 { 29 size_t nleft = n; 30 ssize_t nwrite; 31 32 char *bufp = usrbuf; 33 34 while(nleft > 0) 35 { 36 //nwrite == 0也属于错误 37 if((nwrite = write(fd, bufp, nleft)) <= 0) 38 { 39 if(errno == EINTR) 40 nwrite = 0; 41 else 42 return -1; // -1 和 0 43 } 44 45 nleft -= nwrite; 46 bufp += nwrite; 47 } 48 return n; //这里不是 n- nleft 必须是n 49 } 50 51 //recv_peek选项完成一次正确的读取过程。 52 ssize_t recv_peek(int sockfd, void *buf, size_t len) { 53 int nread; 54 while (1) { 55 //这个过程只成功调用一次 56 nread = recv(sockfd, buf, len, MSG_PEEK); 57 if (nread < 0 && errno == EINTR) { //被中断则继续读取 58 continue; 59 } 60 if (nread < 0) { 61 return -1; 62 } 63 break; 64 } 65 return nread; 66 } 67 68 69 ssize_t readline(int sockfd, void *buf, size_t maxline) { 70 int nread; //一次IO读取的数量 71 int nleft; //还剩余的字节数 72 char *ptr; //存放数据的指针的位置 73 int ret; //readn的返回值 74 int total = 0; //目前总共读取的字节数 75 76 nleft = maxline-1; 77 ptr = buf; 78 79 while (nleft > 0) { 80 //这一次调用仅仅是预览数据 81 //并没有真的把数据从缓冲区中取走 82 ret = recv_peek(sockfd, ptr, nleft); 83 //注意这里读取的字节不够,绝对不是错误!!! 84 if (ret <= 0) { 85 return ret; 86 } 87 88 nread = ret; 89 int i; 90 for (i = 0; i < nread; ++i) { 91 if (ptr[i] == ‘\n‘) { 92 //这里才是真正的读取过程 93 ret = readn(sockfd, ptr, i + 1); 94 if (ret != i + 1) { 95 return -1; 96 } 97 total += ret; 98 ptr += ret; 99 *ptr = 0;100 return total; //返回此行的长度 ‘\n‘包含在其中101 }102 }103 //如果没有发现\n,这些数据应全部接收104 ret = readn(sockfd, ptr, nread);105 if (ret != nread) {106 return -1;107 }108 nleft -= nread;109 total += nread;110 ptr += nread;111 }112 *ptr = 0;113 return maxline-1;114 }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。