阅读背景:

Linux网络编程 -- 多进程实现多用户

来源:互联网 
server.c #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <arpa/inet.h> #include <ctype.h> #include <strings.h> #include <sys/wait.h> #include "wrap.h" #define SERV_PORT 8888 void wait_child(int signo) { //如果>0,继续回收子进程 while (waitpid(0, NULL, WNOHANG) > 0) { ; } } int main() { int i; int n; int cfd; int opt = 1; int listenfd; //文件描述符 pid_t pid; //进程号 char buf[BUFSIZ]; //存放读取到的客户端的数据 char clie_IP[BUFSIZ]; //用来存放客户端IP socklen_t clie_addr_len; struct sockaddr_in serv_addr, clie_addr; //参数1: AF_INET ->ipv4 AF_INET6 ->ipv6 //参数2:SOCK_STREAM -> TCP SOCK_DGRAM -> UDP //参数3:传0 表示使用默认协议。 listenfd = Socket(AF_INET, SOCK_STREAM, 0); //端口复用 setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); bzero(&serv_addr, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(SERV_PORT); //主机字节序转换为网络字节序 大端模式 小端模式 serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); //网络地址为INADDR_ANY,这个宏表示本地的任意IP地址 Bind(listenfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)); //由于历史原因,需强制转换为 struct sockaddr * 类型 Listen(listenfd, 128); //允许同时监听的客户端请求, 最大128 while (1) { clie_addr_len = sizeof(clie_addr); cfd = Accept(listenfd, (struct sockaddr *)&clie_addr, &clie_addr_len); //当有客户端连接 就创建一个进程 pid = fork(); if (0 == pid) { Close(listenfd); while (1) { n = Read(cfd, buf, sizeof(buf)); if (0 == n) { break; } printf("Client IP: %s, Port: %d\n", inet_ntop(AF_INET, &clie_addr.sin_addr.s_addr, clie_IP, sizeof(clie_IP)), ntohs(clie_addr.sin_port)); for (i = 0; i < n; ++i) { buf[i] = toupper(buf[i]); } Write(cfd, buf, n); } Close(cfd); return 0; } else if (pid > 0) { Close(cfd); //回收子进程,防止产生僵尸进程 signal(SIGCHLD, wait_child); } else { perr_exit("fork"); } } return 0; } wrap.c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <sys/socket.h> //输出错误信息并退出 void perr_exit(const char *str) { perror(str); exit(-1); } //创建套接字 带出错处理 哈哈 int Socket(int family, int type, int protocol) { int n; n = socket(family, type, protocol); if (n < 0) { perr_exit("socket error"); } return n; } int Bind(int fd, const struct sockaddr *sa, socklen_t salen) { int n; n = bind(fd, sa, salen); if (n < 0) { perr_exit("bing error"); } return n; } int Listen(int fd, int backlog) { int n; n = listen(fd, backlog); if (n < 0) { perr_exit("listen error"); } return n; } int Connect(int fd, const struct sockaddr *sa, socklen_t salen) { int n; n = connect(fd, sa, salen); if (n < 0) { perr_exit("connect error"); } return n; } int Accept(int fd, struct sockaddr *sa, socklen_t *salenptr) { int n; again: n = accept(fd, sa, salenptr); if (n < 0) { if (errno == ECONNABORTED || errno == EINTR) { goto again; } else { perr_exit("accept error"); } } } ssize_t Read(int fd, void *ptr, size_t nbytes) { ssize_t n; again: n = read(fd, ptr, nbytes); if (-1 == n) { if (EINTR == errno) { goto again; } else { return -1; } } return n; } ssize_t Write(int fd, const void *ptr, size_t nbytes) { ssize_t n; again: n = write(fd, ptr, nbytes); if (-1 == n) { if (EINTR == errno) { goto again; } else { return -1; } } return n; } int Close(int fd) { int n; n = close(fd); if (-1 == n) { perr_exit("close error"); } return n; } server.c #include <stdio.h> #include <unistd.h> #



你的当前访问异常,请进行认证后继续阅读剩余内容。

分享到: