打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Linux环境下服务器和客户端的网络通信

http://www.cnblogs.com/fanyabo/archive/2012/06/15/2551432.html

2012

  UNIX系统中的网络协议是这样分层的:1.应用层(telnet,ftp等);2.主机到主机传输层(TCP,UDP);3.Internet层(IP和路由);4.网络访问层(网络,数据链路,物理层)。
  套接口描述符使用 sockaddr_in 数据结构,有了套接口之后需要调用bind()函数把套接口绑定到本地计算机的一个接口上,使用inet_addr()函数将普遍形式的IP地址转化为无符号的整型数,调用socket()函数获得文件描述符。程序分为客户端和服务端。应用select函数来实现异步的读写操作。在服务器端:首先先创建套接字,然后绑定,接下进入一个无限循环,用accept函数,接受“连接”请求,然后调用创建线程函数,创造新的线程,进入下一个循环。这样每当有一个新的“连接”被接受都会创建一个新的线程。

服务器端程序如下:

//server.c

  1 //server.c  2 #include <stdio.h>  3 #include <stdlib.h>  4 #include <errno.h>  5 #include <string.h>  6 #include <sys/types.h>  7 #include <netinet/in.h>  8 #include <sys/socket.h>  9 #include <sys/wait.h> 10 #include <unistd.h> 11 #include <arpa/inet.h> 12 #include <sys/time.h> 13 #include <sys/types.h> 14  15 #define MAXBUF 1024 16  17  18 int main(int argc, char **argv) 19 { 20     int sockfd, new_fd; 21     socklen_t len; 22     struct sockaddr_in my_addr, their_addr; 23     unsigned int myport, lisnum; 24     char buf[MAXBUF + 1]; 25     fd_set rfds; 26     struct timeval tv; 27     int retval, maxfd = -1; 28  29     if (argv[1]) 30         myport = atoi(argv[1]); 31     else 32         myport = 7838; 33  34     if (argv[2]) 35         lisnum = atoi(argv[2]); 36     else 37         lisnum = 2; 38  39     if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1)  40    { 41         perror("socket"); 42         exit(1); 43     } 44  45     bzero(&my_addr, sizeof(my_addr)); 46     my_addr.sin_family = PF_INET; 47     my_addr.sin_port = htons(myport); 48     if (argv[3]) 49         my_addr.sin_addr.s_addr = inet_addr(argv[3]); 50     else 51         my_addr.sin_addr.s_addr = INADDR_ANY; 52  53     if (bind(sockfd, (struct sockaddr *) &my_addr, sizeof(struct sockaddr)) 54         == -1) { 55         perror("bind"); 56         exit(1); 57     } 58  59     if (listen(sockfd, lisnum) == -1) { 60         perror("listen"); 61         exit(1); 62     } 63  64     while (1) { 65         printf 66             (" ----等待新的连接到来开始新的聊天…… "); 67         len = sizeof(struct sockaddr); 68         if ((new_fd = 69              accept(sockfd, (struct sockaddr *) &their_addr, 70                     &len)) == -1) { 71             perror("accept"); 72             exit(errno); 73         } else 74             printf("server: got connection from %s, port %d, socket %d ", 75                    inet_ntoa(their_addr.sin_addr), 76                    ntohs(their_addr.sin_port), new_fd); 77  78         /* 开始处理每个新连接上的数据收发 */ 79         printf 80      (" 准备就绪,可以开始聊天了……输入消息回车即可发信息给对方 "); 81         while (1) { 82             /* 把集合清空 */ 83             FD_ZERO(&rfds); 84             /* 把标准输入句柄0加入到集合中 */ 85             FD_SET(0, &rfds); 86             maxfd = 0; 87             /* 把当前连接句柄new_fd加入到集合中 */ 88             FD_SET(new_fd, &rfds); 89             if (new_fd > maxfd) 90                 maxfd = new_fd; 91             /* 设置最大等待时间 */ 92             tv.tv_sec = 1; 93             tv.tv_usec = 0; 94             /* 开始等待 */ 95             retval = select(maxfd + 1, &rfds, NULL, NULL, &tv); 96             if (retval == -1) { 97                 printf("将退出,select出错! %s", strerror(errno)); 98                 break; 99             } else if (retval == 0) {100                 /* printf101               ("没有任何消息到来,用户也没有按键,继续等待…… "); */102                 continue;103             } else {104                 if (FD_ISSET(0, &rfds)) {105                     /* 用户按键了,则读取用户输入的内容发送出去 */106                     bzero(buf, MAXBUF + 1);107                     fgets(buf, MAXBUF, stdin);108                     if (!strncasecmp(buf, "quit", 4)) {109                         printf("自己请求终止聊天! ");110                         break;111                     }112                     len = send(new_fd, buf, strlen(buf) - 1, 0);113                     if (len > 0)114                         printf115                       ("消息:%s 发送成功,共发送了%d个字节! ",116                              buf, len);117                     else {118                         printf119                  ("消息'%s'发送失败!错误代码是%d,错误信息是'%s' ",120                              buf, errno, strerror(errno));121                         break;122                     }123                 }124                 if (FD_ISSET(new_fd, &rfds)) {125      /* 当前连接的socket上有消息到来则接收对方发过来的消息并显示 */126                     bzero(buf, MAXBUF + 1);127                     /* 接收客户端的消息 */128                     len = recv(new_fd, buf, MAXBUF, 0);129                     if (len > 0)130                         printf131                       ("接收消息成功:'%s',共%d个字节的数据 ",132                              buf, len);133                     else {134                         if (len < 0)135                             printf136                    ("消息接收失败!错误代码是%d,错误信息是'%s' ",137                                  errno, strerror(errno));138                         else139                             printf("对方退出了,聊天终止 ");140                         break;141                     }142                 }143             }144         }145         close(new_fd);146         /* 处理每个新连接上的数据收发结束 */147         printf("还要和其它连接聊天吗?(no->退出)");148         fflush(stdout);149         bzero(buf, MAXBUF + 1);150         fgets(buf, MAXBUF, stdin);151         if (!strncasecmp(buf, "no", 2)) {152             printf("终止聊天! ");153             break;154         }155     }156 157     close(sockfd);158     return 0;159 }

客户端程序如下:

//client.c

  1 #include <stdio.h>  2 #include <string.h>  3 #include <errno.h>  4 #include <sys/socket.h>  5 #include <resolv.h>  6 #include <stdlib.h>  7 #include <netinet/in.h>  8 #include <arpa/inet.h>  9 #include <unistd.h> 10 #include <sys/time.h> 11 #include <sys/types.h> 12  13 #define MAXBUF 1024 14  15 int main(int argc, char **argv) 16 { 17     int sockfd, len; 18     struct sockaddr_in dest; 19     char buffer[MAXBUF + 1]; 20     fd_set rfds; 21     struct timeval tv; 22     int retval, maxfd = -1; 23  24     if (argc != 3) { 25         printf 26         ("参数错误!正确用法如下: %s IP地址 端口 比如: %s 127.0.0.1 80 此程序从某个IP地址的服务器某个端口接收最多MAXBUF个字节的消息", 27              argv[0], argv[0]); 28         exit(0); 29     } 30     /* 创建一个 socket 用于 tcp 通信 */ 31     if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 32         perror("Socket"); 33         exit(errno); 34     } 35  36     /* 初始化服务器端(对方)的地址和端口信息 */ 37     bzero(&dest, sizeof(dest)); 38     dest.sin_family = AF_INET; 39     dest.sin_port = htons(atoi(argv[2])); 40     if (inet_aton(argv[1], (struct in_addr *) &dest.sin_addr.s_addr) == 0) { 41         perror(argv[1]); 42         exit(errno); 43     } 44  45     /* 连接服务器 */ 46     if (connect(sockfd, (struct sockaddr *) &dest, sizeof(dest)) != 0) { 47         perror("Connect "); 48         exit(errno); 49     } 50  51     printf 52    (" 准备就绪,可以开始聊天了……输入消息回车即可发信息给对方 "); 53     while (1) { 54         /* 把集合清空 */ 55         FD_ZERO(&rfds); 56         /* 把标准输入句柄0加入到集合中 */ 57         FD_SET(0, &rfds); 58         maxfd = 0; 59         /* 把当前连接句柄sockfd加入到集合中 */ 60         FD_SET(sockfd, &rfds); 61         if (sockfd > maxfd) 62             maxfd = sockfd; 63         /* 设置最大等待时间 */ 64         tv.tv_sec = 1; 65         tv.tv_usec = 0; 66         /* 开始等待 */ 67         retval = select(maxfd + 1, &rfds, NULL, NULL, &tv); 68         if (retval == -1) { 69             printf("将退出,select出错! %s", strerror(errno)); 70             break; 71         } else if (retval == 0) { 72             /* printf 73                ("没有任何消息到来,用户也没有按键,继续等待…… "); */ 74             continue; 75         } else { 76             if (FD_ISSET(sockfd, &rfds)) { 77          /* 连接的socket上有消息到来则接收对方发过来的消息并显示 */ 78                 bzero(buffer, MAXBUF + 1); 79               /* 接收对方发过来的消息,最多接收 MAXBUF 个字节 */ 80                 len = recv(sockfd, buffer, MAXBUF, 0); 81                 if (len > 0) 82                     printf 83                         ("接收消息成功:'%s',共%d个字节的数据 ", 84                          buffer, len); 85                 else { 86                     if (len < 0) 87                         printf 88                     ("消息接收失败!错误代码是%d,错误信息是'%s' ", 89                              errno, strerror(errno)); 90                     else 91                         printf("对方退出了,聊天终止! "); 92                     break; 93                 } 94             } 95             if (FD_ISSET(0, &rfds)) { 96                 /* 用户按键了,则读取用户输入的内容发送出去 */ 97                 bzero(buffer, MAXBUF + 1); 98                 fgets(buffer, MAXBUF, stdin); 99                 if (!strncasecmp(buffer, "quit", 4)) {100                     printf("自己请求终止聊天! ");101                     break;102                 }103                 /* 发消息给服务器 */104                 len = send(sockfd, buffer, strlen(buffer) - 1, 0);105                 if (len < 0) {106                     printf107                  ("消息'%s'发送失败!错误代码是%d,错误信息是'%s' ",108                          buffer, errno, strerror(errno));109                     break;110                 } else111                     printf112                       ("消息:%s 发送成功,共发送了%d个字节! ",113                          buffer, len);114             }115         }116     }117     /* 关闭连接 */118     close(sockfd);119     return 0;120 }

编译过程:gcc -Wall server.c -o server
         gcc -Wall client.c -o client

运行:在一个终端里运行  ./server 3490 1  模拟服务器端,其中3490指本地接口
     在另一个终端运行  ./client 127.0.0.1 3490  模拟客户端,最后一个参数应与服务器定义的接口相同

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
如何判断socket已经断开
网络socket编程指南
epoll同时处理海量连接的代码
Linux环境下的Socket编程 - C&C - Linux技术中坚站
Linux环境下的网络编程
socket网络编程快速上手(二)——细节问题(5)(完结篇)
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服