• 无连接的数据传输


     

    用于无连接套接字的读写函数情况要复杂一点。由于没有建立一个连接,所以每次发送数据的过程中都要明确指明该数据包的地址,同时,在接收数据包的时候,接受进程能够得到发送该数据包的地址,从而知道该数据包从哪里来。

    Linux环境中提供有专门对无连接的套接字进行读写的函数,这两个函数分别为sendto函数和recvfrom函数,函数原型如下:

     int sendto(int sockfd, const *restrict buf, size_t len, int flags, struct sockaddr * restrict destaddr, socket_len *restrict destlen); 

    头文件: #include <sys/types.h> #include <sys/socket.h> 

    参数说明:

    第一个参数sockfd表示通信用的套接字。

    第二个参数buf表示发送内容所在的缓冲区。

    第三个参数len表示需要发送的字节数。

    第四个参数flags是传输标志位,一般设0,详细描述请参考send()。

    第五个参数destaddr是一个sockaddr地址结构的地址,该地址表示数据报的目的地,结构sockaddr 请参考bind。

    第六个参数destlen表示数据报目的地址结构大小。

    返回值:成功返回实际传送出去的字符数,失败返回-1。

     int recvfrom (int sockfd, const *restrict buf, size_t len, int flags, struct sockaddr * restrict addr, socket_len *restrict addrlen); 

    头文件: #include <sys/types.h> #include <sys/socket.h> 

    参数说明:

    第一个参数sockfd表示通信用的套接字。

    第二个参数buf表示存储接收数据的缓冲区。

    第三个参数len表示需要接收的字节数。

    第四个参数flags是传输标志位。

    第五个参数addr是一个sockaddr地址结构的地址,该地址表示数据报的发送地址。

    第六个参数addrlen表示数据报目的地址结构大小。

    无连接的数据传说一般使用的是UDP协议,还是使用大小写字母转换的例子来演示无连接服务的服务器端程序。无连接服务器端执行流程如下:

     

    服务器端程序代码如下所示:

    #include <stdio.h>
    #include <string.h>
    #include <unistd.h>
    #include <ctype.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <stdlib.h>
    #include <errno.h>
    #define MAX_LINE 100
    
    /*处理函数,将大写字符转换成小写字符。参数为需要转换的字符串*/
    void my_fun(char *p)
    {
           if(p == NULL)
                  return ;
           for(; *p != ''; p++)
                  if(*p >= 'A' && *p <= 'Z')
                         *p = *p - 'A' + 'a';
    }
    
    int main(void)
    {
           struct sockaddr_in sin;
           struct sockaddr_in cin;
           int s_fd;
           int port = 8000;
           socklen_t addr_len;
           char buf[MAX_LINE];
           char addr_p[INET_ADDRSTRLEN];
           int n;
           /*填写地址结构*/
           bzero(&sin, sizeof(sin));
           sin.sin_family = AF_INET;
           sin.sin_addr.s_addr = INADDR_ANY;
           sin.sin_port = htons(port);
           /*使用UDP通信协议创建一个套接字,并且得到发送本数据包的客户端地址*/
           s_fd = socket(AF_INET, SOCK_DGRAM, 0);
           if(s_fd == -1)
           {
                  perror("fail to create socket");
                  exit(1);
           }
           /*将套接字绑定到一个地址*/
           if(bind(s_fd, (struct sockaddr *)&sin, sizeof(sin)) == -1)
           {
                  perror("call to bind");
                  exit(1);
           }
    
           /*服务器是一个死循环,一次循环处理一个请求*/
           while(1)
           {
                  addr_len = sizeof(sin);
                  /*UDP协议是无连接的,所以只有一个套接字接受客户端传输的数据报即可
                   *而不需要在创建一个套接字,用于建立连接
                   *同样的使用UDP协议的网络程序也不需要调用accept函数
                  **/
                   ///接收客户端传送过来的字符串
                  n = recvfrom(s_fd, buf, MAX_LINE, 0, (struct sockaddr *) &cin, &addr_len);
                  if(n == -1)
                  {
                         perror("fail to receive");
                         exit(1);
                  }
                  /*将客户端地址转换成字符串*/
                  inet_ntop(AF_INET, &cin.sin_addr, addr_p, sizeof(addr_p));
                  printf("client IP is %s, port is %d
    ", addr_p, ntohs(cin.sin_port));     ///打印客户端地址和端口号
                  printf("content is : %s
    ", buf);            ///打印客户端发送过来的字符串
                  my_fun(buf);
                  /*使用sendto函数将转换后的字符串回传给客户端程序*/
                  n = sendto(s_fd, buf, n, 0, (struct sockaddr *) &cin, addr_len);
                  if(n == -1)
                  {
                         perror("fail to send");
                         exit(1);
                  }
           }
           if(close(s_fd) == -1)
           {
                  perror("fail to close");
                  exit(1);
           }
           return 0;
    }

    客户端程序代码如下:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <errno.h>
    #define MAX_LINE 80
    
    int main(int argc, char *argv[ ])
    {
           struct sockaddr_in sin;
           struct sockaddr_in cin;
           int port = 8000;
           socklen_t addr_len;
           int s_fd;
           char *str = "test";
           char buf[MAX_LINE];
           char add_p[INET_ADDRSTRLEN];
           int n;
           if(argc != 2)
           {
                  printf("wrong command
    ");
                  exit(1);
           }
           str = argv[1];
           bzero(&sin, sizeof(sin));
           /*使用IP地址族*/
           sin.sin_family = AF_INET;
           /*与本机的服务器程序通信,使用本机的IP地址*/
           inet_pton(AF_INET, "127.0.0.1", &sin.sin_addr);
           sin.sin_port = htons(port);
           s_fd = socket(AF_INET, SOCK_DGRAM, 0);
           if(s_fd == -1)
           {
                  perror("fail to create socket");
                  exit(1);
           }
           sprintf(buf, "%s", str);
           n = sendto(s_fd, buf, strlen(str) + 1, 0, (struct sockaddr *)&sin, sizeof(sin));
           if(n == -1)
           {
                  perror("fail to send
    ");
                  exit(1);
           }
           addr_len = sizeof(cin);
           n = recvfrom(s_fd, buf, MAX_LINE, 0, (struct sockaddr *) &cin, &addr_len);
           if(n == -1)
           {
                  perror("fail to receive");
                  exit(1);
           }
           else
                  printf("receive from server : %s
    ", buf);
           if(close(s_fd) == -1)
           {
                  perror("fail to close");
                  exit(1);
           }
           return 0;
    }
  • 相关阅读:
    “家亡血史,原应叹息”
    SQLite初体验
    两张表数据同步用触发器
    openstack 后期维护(四)--- 删除僵尸卷
    Python3 装逼神器---词云(wordcloud)
    (三)FastDFS 高可用集群架构学习---Client 接口开发
    (四)FastDFS 高可用集群架构学习---后期运维--基础知识及常用命令
    (二)FastDFS 高可用集群架构学习---搭建
    (一)FastDFS 高可用集群架构学习---简介
    Python3使用Print输出彩色字体
  • 原文地址:https://www.cnblogs.com/Mr--Yang/p/6754421.html
Copyright © 2020-2023  润新知