Linux 网络编程一步一步学(六)客户/服务端通信

CLIENT

    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 #define MAXBUF 1024
   11 int main(int argc, char **argv)
-  12 {
|  13     int sockfd, len;
|  14     struct sockaddr_in dest;
|  15     char buffer[MAXBUF + 1];
-  16     if (argc != 3) {
2  17         printf("参数格式错误!正确用法如下:\n\t\t%s IP 地址 端口\n\t比如:\t%s 127.0.0.1 80\n此程序用来从某个 IP 地址的服务器某个端口接收最多 MAXBUF 个字节的消息",argv[0], argv[0]);
2  18         exit(0);
2  19     }
|  20     /* 创建一个 socket 用于 tcp 通信 */
-  21     if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
2  22         perror("Socket");
2  23         exit(errno);
2  24     }
|  25     printf("socket created\n");
|  26     /* 初始化服务器端(对方)的地址和端口信息 */
|  27     bzero(&dest, sizeof(dest));
|  28     dest.sin_family = AF_INET;
|  29     dest.sin_port = htons(atoi(argv[2]));
-  30     if (inet_aton(argv[1], (struct in_addr *) &dest.sin_addr.s_addr) == 0) {
2  31         perror(argv[1]);
2  32         exit(errno);
2  33     }
|  34     printf("address created\n");
|  35     /* 连接服务器 */
-  36     if (connect(sockfd, (struct sockaddr *) &dest, sizeof(dest)) != 0) {
2  37         perror("Connect ");
2  38         exit(errno);
2  39     }
|  40     printf("server connected\n");
|  41     /* 接收对方发过来的消息,最多接收 MAXBUF 个字节 */
|  42     bzero(buffer, MAXBUF + 1);
|  43     /* 接收服务器来的消息 */
|  44     len = recv(sockfd, buffer, MAXBUF, 0);
|  45     if(len > 0) printf("接收消息成功:'%s',共%d个字节的数据\n", buffer, len);
|  46     else printf("消息接收失败!错误代码是%d,错误信息是'%s'\n", errno, strerror(errno));
|  47     bzero(buffer, MAXBUF + 1);
|  48     strcpy(buffer, "这是客户端发给服务器端的消息\n");
|  49     /* 发消息给服务器 */
|  50     len = send(sockfd, buffer, strlen(buffer), 0);
|  51     if(len < 0) printf("消息'%s'发送失败!错误代码是%d,错误信息是'%s'\n", buffer,errno, strerror(errno));
|  52     else printf("消息'%s'发送成功,共发送了%d个字节!\n", buffer, len);
|  53     /* 关闭连接 */
|  54     close(sockfd);
|  55     return 0;
|  56 }
   57   

SERVER

    1 #include <stdio.h>                                                                                           
    2 #include <stdlib.h>
    3 #include <errno.h>
    4 #include <string.h>
    5 #include <sys/types.h>
    6 #include <netinet/in.h>
    7 #include <sys/socket.h>
    8 #include <sys/wait.h>
    9 #include <unistd.h>
   10 #include <arpa/inet.h>
   11 #define MAXBUF 1024
   12 int main(int argc, char **argv)
-  13 {
|  14     int sockfd, new_fd;
|  15     socklen_t len;
|  16     struct sockaddr_in my_addr, their_addr;
|  17     unsigned int myport, lisnum;
|  18     char buf[MAXBUF + 1];
|  19     if (argv[1])
|  20         myport = atoi(argv[1]);
|  21     else
|  22         myport = 7838;
|  23     if (argv[2])
|  24         lisnum = atoi(argv[2]);
|  25     else
|  26         lisnum = 2;
-  27     if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
2  28         perror("socket");
2  29         exit(1);
2  30     }
|  31     else printf("socket created\n");
|  32 
|  33     bzero(&my_addr, sizeof(my_addr));
|  34     my_addr.sin_family = PF_INET;
|  35     my_addr.sin_port = htons(myport);
|  36     if(argv[3])
|  37         my_addr.sin_addr.s_addr = inet_addr(argv[3]);
|  38     else
|  39         my_addr.sin_addr.s_addr = INADDR_ANY;
|  40     if (bind(sockfd, (struct sockaddr *) &my_addr, sizeof(struct sockaddr)) == -1)
-  41     {
2  42         perror("bind");
2  43         exit(1);
2  44     }
|  45     else printf("binded\n");
-  46     if (listen(sockfd, lisnum) == -1) {
2  47         perror("listen");
2  48         exit(1);
2  49     }
|  50     else printf("begin listen\n");
-  51     while(1) {
2  52         len = sizeof(struct sockaddr);
-  53         if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &len)) == -1) {
3  54             perror("accept");
3  55             exit(errno);
3  56         }
2  57         else
2  58             printf("server: got connection from %s, port %d, socket%d\n",inet_ntoa(their_addr.sin_addr), ntohs(their_ad2dr.sin_port), new_fd);
2  59         /* 开始处理每个新连接上的数据收发 */
2  60         bzero(buf, MAXBUF + 1);
2  61         strcpy(buf, "这是在连接建立成功后向客户端发送的第一个消息\n只能向new_fd这个用accept函数新建立的socket发消息,不能向sockfd这个监听socket发送消息,监听socket不能用来接收或发送消息\n");
2  62         /* 发消息给客户端 */
2  63         len = send(new_fd, buf, strlen(buf), 0);
-  64         if(len < 0) {
3  65             printf("消息'%s'发送失败!错误代码是%d,错误信息是'%s'\n", buf, errno,
3  66             strerror(errno));
3  67         }
2  68         else printf("消息'%s'发送成功,共发送了%d个字节!\n", buf, len);
2  69         bzero(buf, MAXBUF + 1);
2  70         /* 接收客户端的消息 */
2  71         len = recv(new_fd, buf, MAXBUF, 0);
2  72         if(len > 0) printf("接收消息成功:'%s',共%d个字节的数据\n", buf, len);
2  73         else printf("消息接收失败!错误代码是%d,错误信息是'%s'\n", errno, strerror(errno));
2  74         /* 处理每个新连接上的数据收发结束 */
2  75     }
|  76     close(sockfd);
|  77     return 0;
|  78 }
   79    

函数解释:

  accept():用来接受参数s 的socket 连线. 参数s 的socket 必需先经bind()、listen()函数处理过, 当有连线进来时accept()会返回一个新的socket 处理代码, 往后的数据传送与读取就是经由新的socket处理, 而原来参数s 的socket 能继续使用accept()来接受新的连线要求. 连线成功时, 参数addr 所指的结构会被系统填入远程主机的地址数据, 参数addrlen 为scokaddr 的结构长度. 关于机构sockaddr 的定义请参考bind().

  int accept(int s, struct sockaddr * addr, int * addrlen);
函数说明:accept()用来接受参数s 的socket 连线. 参数s 的socket 必需先经bind()、listen()函数处理过, 当有连线进来时accept()会返回一个新的socket 处理代码, 往后的数据传送与读取就是经由新的socket处理, 而原来参数s 的socket 能继续使用accept()来接受新的连线要求. 连线成功时, 参数addr 所指的结构会被系统填入远程主机的地址数据, 参数addrlen 为scokaddr 的结构长度. 关于机构sockaddr 的定义请参考bind().

原文地址:https://www.cnblogs.com/liqiu/p/2981321.html