1. 首页
  2. 开发
  3. C/C++

Linux C/C++ UDP Socket通信实例

环境:Linux

语言:C/C++

通信方式:UDP

服务器端的步骤如下:

1. socket:      建立一个socket

2. bind:          将这个socket绑定在某个端口上(AF_INET)

3. recvfrom:  如果没有客户端发起请求,则会阻塞在这个函数里

4. close:        通信完成后关闭socket

客户端的步骤如下:

1. socket:      建立一个socket

2. sendto:     向服务器的某个端口发起请求(AF_INET)

3. close:        通信完成后关闭socket

 

基于UDP的接收和发送函数

int recvfrom(int sockfd, void * buf, size_t len, int flags, struct sockaddr * src_addr, socklen_t * addrlen);

int sendto(int sockfd, const void * buf, size_t len, int flags, const struct sockaddr * dest_addr, socklen_t addrlen);

UDP套接字不会保持连接状态,每次传输数据都要添加目标地址信息,这相当于在邮寄包裹前填写收件人地址。

 

recvfrom用于接收数据,sendto用于发送数据

recvfrom:

  • sockfd:用于接收UDP数据的套接字;
  • buf:保存接收数据的缓冲区地址;
  • len:可接收的最大字节数(不能超过buf缓冲区的大小);
  • flags:可选项参数,若没有可传递0;
  • src_addr:存有发送端地址信息的sockaddr结构体变量的地址;
  • addrlen:保存参数 src_addr的结构体变量长度的变量地址值。

sendto:

  • sockfd:用于传输UDP数据的套接字;
  • buf:保存待传输数据的缓冲区地址;
  • len:带传输数据的长度(以字节计);
  • flags:可选项参数,若没有可传递0;
  • dest_addr:存有目标地址信息的 sockaddr 结构体变量的地址;
  • addrlen:传递给参数 dest_addr的地址值结构体变量的长度。

 

Server.cpp

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>

#define SERV_PORT   8000

int main()
{
  /* sock_fd --- socket文件描述符 创建udp套接字*/
  int sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
  if(sock_fd < 0)
  {
    perror("socket");
    exit(1);
  }

  /* 将套接字和IP、端口绑定 */
  struct sockaddr_in addr_serv;
  int len;
  memset(&addr_serv, 0, sizeof(struct sockaddr_in));  //每个字节都用0填充
  addr_serv.sin_family = AF_INET;              //使用IPV4地址
  addr_serv.sin_port = htons(SERV_PORT);          //端口
  /* INADDR_ANY表示不管是哪个网卡接收到数据,只要目的端口是SERV_PORT,就会被该应用程序接收到 */
  addr_serv.sin_addr.s_addr = htonl(INADDR_ANY);  //自动获取IP地址
  len = sizeof(addr_serv);

  /* 绑定socket */
  if(bind(sock_fd, (struct sockaddr *)&addr_serv, sizeof(addr_serv)) < 0)
  {
    perror("bind error:");
    exit(1);
  }


  int recv_num;
  int send_num;
  char send_buf[20] = "i am server!";
  char recv_buf[20];
  struct sockaddr_in addr_client;

  while(1)
  {
    printf("server wait:\n");

    recv_num = recvfrom(sock_fd, recv_buf, sizeof(recv_buf), 0, (struct sockaddr *)&addr_client, (socklen_t *)&len);

    if(recv_num < 0)
    {
      perror("recvfrom error:");
      exit(1);
    }

    recv_buf[recv_num] = '\0';
    printf("server receive %d bytes: %s\n", recv_num, recv_buf);

    send_num = sendto(sock_fd, send_buf, recv_num, 0, (struct sockaddr *)&addr_client, len);

    if(send_num < 0)
    {
      perror("sendto error:");
      exit(1);
    }
  }

  close(sock_fd);

  return 0;
}

Client.cpp

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>


#define DEST_PORT 8000
#define DSET_IP_ADDRESS  "127.0.0.1"


int main()
{
  /* socket文件描述符 */
  int sock_fd;

  /* 建立udp socket */
  sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
  if(sock_fd < 0)
  {
    perror("socket");
    exit(1);
  }

  /* 设置address */
  struct sockaddr_in addr_serv;
  int len;
  memset(&addr_serv, 0, sizeof(addr_serv));
  addr_serv.sin_family = AF_INET;
  addr_serv.sin_addr.s_addr = inet_addr(DSET_IP_ADDRESS);
  addr_serv.sin_port = htons(DEST_PORT);
  len = sizeof(addr_serv);


  int send_num;
  int recv_num;
  char send_buf[20] = "hey, who are you?";
  char recv_buf[20];

  printf("client send: %s\n", send_buf);

  send_num = sendto(sock_fd, send_buf, strlen(send_buf), 0, (struct sockaddr *)&addr_serv, len);

  if(send_num < 0)
  {
    perror("sendto error:");
    exit(1);
  }

  recv_num = recvfrom(sock_fd, recv_buf, sizeof(recv_buf), 0, (struct sockaddr *)&addr_serv, (socklen_t *)&len);

  if(recv_num < 0)
  {
    perror("recvfrom error:");
    exit(1);
  }

  recv_buf[recv_num] = '\0';
  printf("client receive %d bytes: %s\n", recv_num, recv_buf);

  close(sock_fd);

  return 0;
}

程序运行截图:

client向服务器发送了“hey, who are you?”的字符串,server返回”i am server!”的字符串。

原创文章,作者:admin,如若转载,请注明出处:https://www.huiyingwu.com/4465/

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注