• 面向连接的echo服务编程实例


    以下是echo_serv.c的源码,提供创建服务端,绑定套接字到本机IP的8080端口,当收到客户端发送的字符串就在屏幕上打印出来,并且把字符串发送给客户端

     1 // echo_serv.c – gcc –o s echo_serv.c
     2 #include <sys/types.h>
     3 #include <sys/socket.h>
     4 #include <netinet/in.h>
     5 #include <arpa/inet.h>
     6 #include <unistd.h>
     7 #include <stdio.h>
     8 #include <errno.h>
     9 
    10 #define EHCO_PORT 8080
    11 #define MAX_CLIENT_NUM 10
    12 
    13 int main()
    14 {
    15   int sock_fd;
    16   struct sockaddr_in serv_addr;
    17   int clientfd;
    18   struct sockaddr_in clientAdd;
    19   char buff[101];
    20   socklen_t len;
    21   int closing =0;
    22   int n;
    23 
    24   /* 创建socket */
    25   sock_fd = socket(AF_INET, SOCK_STREAM, 0);
    26   if(sock_fd==-1) {
    27     perror("create socket error!");
    28     return 0;
    29   } else {
    30     printf("Success to create socket %d
    ", sock_fd);
    31   }
    32 
    33   /* 设置server地址结构 */
    34   bzero(&serv_addr, sizeof(serv_addr));                // 初始化结构占用的内存
    35   serv_addr.sin_family = AF_INET;                    // 设置地址传输层类型
    36   serv_addr.sin_port = htons(EHCO_PORT);            // 设置监听端口
    37   //serv_addr.sin_addr.s_addr = htons(INADDR_ANY);    // 设置服务器地址  //用这个不能实现在不同主机上的通讯
    38   serv_addr.sin_addr.s_addr = inet_addr("192.168.13.145");    // 设置服务器地址
    39   
    40   bzero(&(serv_addr.sin_zero), 8);
    41 
    42   /* 把地址和套接字绑定 */
    43   if(bind(sock_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr))!= 0) {
    44     printf("bind address fail! %d
    ", errno);
    45     close(sock_fd);
    46     return 0;
    47   } else {
    48     printf("Success to bind address!
    ");
    49   }
    50 
    51   /* 设置套接字监听 */
    52   if(listen(sock_fd ,MAX_CLIENT_NUM) != 0) {
    53     perror("listen socket error!
    ");
    54     close(sock_fd);
    55     return 0;
    56   } else {
    57     printf("Success to listen
    ");
    58   }
    59 
    60   /* 创建新连接对应的套接字 */
    61   len = sizeof(clientAdd);
    62   clientfd = accept(sock_fd, (struct sockaddr*)&clientAdd, &len);
    63   if (clientfd<=0) {
    64     perror("accept() error!
    ");
    65     close(sock_fd);
    66     return 0;
    67   }
    68 
    69   /* 接收用户发来的数据 */
    70   while((n = recv(clientfd,buff, 100,0 )) > 0) {
    71     buff[n] = ''; // 给字符串加入结束符
    72     printf("number of receive bytes = %d data = %s
    ", n, buff);        // 打印字符串长度和内容
    73     fflush(stdout);
    74     send(clientfd, buff, n, 0);            // 发送字符串内容给客户端
    75     if(strncmp(buff, "quit", 4) == 0)        // 判断是否是退出命令
    76       break;
    77   }
    78 
    79   close(clientfd);                        // 关闭新建的连接
    80   close(sock_fd);                    // 关闭服务端监听的socket
    81 
    82   return 0;
    83 }
    View Code

    然后是客户端程序,在和服务器建立连接后发送字符串到服务器端,并且接受服务器发送的字符串显示在屏幕上

     1 // echo_client – gcc –o c echo_client.c
     2 #include <sys/types.h>
     3 #include <sys/socket.h>
     4 #include <netinet/in.h>
     5 #include <arpa/inet.h>
     6 #include <unistd.h>
     7 #include <stdio.h>
     8 #include <errno.h>
     9 
    10 #define EHCO_PORT 8080
    11 #define MAX_COMMAND 5
    12 
    13 int main()
    14 {
    15   int sock_fd;
    16   struct sockaddr_in serv_addr;
    17 
    18   char *buff[MAX_COMMAND] = {"abc", "def", "test", "hello", "quit"};
    19   char tmp_buf[100];
    20   socklen_t len;
    21   int n, i;
    22 
    23   /* 创建socket */
    24   sock_fd = socket(AF_INET, SOCK_STREAM, 0);
    25   if(sock_fd==-1) {
    26     perror("create socket error!");
    27     return 0;
    28   } else {
    29     printf("Success to create socket %d
    ", sock_fd);
    30   }
    31 
    32   /* 设置server地址结构 */
    33   bzero(&serv_addr, sizeof(serv_addr));                // 初始化结构占用的内存
    34   serv_addr.sin_family = AF_INET;                    // 设置地址传输层类型
    35   serv_addr.sin_port = htons(EHCO_PORT);            // 设置监听端口
    36   //serv_addr.sin_addr.s_addr = htons(INADDR_ANY);        // 设置服务器地址  //用这个不能实现在不同主机上的通讯
    37   serv_addr.sin_addr.s_addr = inet_addr("192.168.13.145");    // 设置服务器地址
    38   bzero(&(serv_addr.sin_zero), 8);
    39 
    40   /* 连接到服务端 */
    41   if (-1==connect(sock_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr))) {
    42     perror("connect() error!
    ");
    43     close(sock_fd);
    44     return 0;
    45   }
    46   printf("Success connect to server!
    ");
    47 
    48   /* 发送并接收缓冲的数据 */
    49   for (i=0;i<MAX_COMMAND;i++) {
    50     send(sock_fd, buff[i], 100, 0);                        // 发送数据给服务端
    51     n = recv(sock_fd, tmp_buf, 100, 0);                    // 从服务端接收数据
    52     tmp_buf[n] = '';  // 给字符串添加结束标志
    53     printf("data send: %s receive: %s
    ", buff[i], tmp_buf);        // 打印字符串
    54     if (0==strncmp(tmp_buf, "quit", 4))                    // 判断是否是退出命令
    55       break;
    56   }
    57 
    58   close(sock_fd);                                    // 关闭套接字
    59 
    60   return 0;
    61 }
    View Code

    关于htos补充一下,也是摘自其它博主的吧

    在C/C++写网络程序的时候,往往会遇到字节的网络顺序和主机顺序的问题。这是就可能用到htons(), ntohl(), ntohs(),htons()这4个函数。
    网络字节顺序与本地字节顺序之间的转换函数:

    htonl()--"Host to Network Long"
    ntohl()--"Network to Host Long"
    htons()--"Host to Network Short"
    ntohs()--"Network to Host Short"

    之所以需要这些函数是因为计算机数据表示存在两种字节顺序:NBO与HBO

    网络字节顺序NBO(Network Byte Order): 按从高到低的顺序存储,在网络上使用统一的网络字节顺序,可以避免兼容性问题。

    主机字节顺序(HBO,Host Byte Order): 不同的机器HBO不相同,与CPU设计有关,数据的顺序是由cpu决定的,而与操作系统无关。
    如 Intel x86结构下, short型数0x1234表示为34 12, int型数0x12345678表示为78 56 34 12  
    如 IBM power PC结构下, short型数0x1234表示为12 34, int型数0x12345678表示为12 34 56 78
       
    由于这个原因不同体系结构的机器之间无法通信,所以要转换成一种约定的数序,也就是网络字节顺序,其实就是如同power pc那样的顺序. 在PC开发中有ntohl和htonl函数可以用来进行网络字节和主机字节的转换.

    说白了其实不过只是大端方式小端方式的转换

  • 相关阅读:
    Mysql经常使用函数
    ZOJ 3690 Choosing number
    cocos2d-x 多触点监听
    ansible不配ssh连接,用户密码登录
    Ansible Role
    关闭centos自动升级内核
    让外部网络访问K8S service的四种方式
    Hadoop实战:Hadoop分布式集群部署(一)
    Docker:搭建私有仓库(Registry 2.4)
    Docker下的Spring Cloud三部曲之一:极速体验
  • 原文地址:https://www.cnblogs.com/fallenmoon/p/6879399.html
Copyright © 2020-2023  润新知