用c++实现一个简单的udp echo服务器
Anbinx
2021-02-22 AM
7℃
0条
/**
* @file udp_server.cpp
* @author anbinx
* @brief a simple udp echo server
* @date 2021-02-22
*
* @copyright Copyright (c) 2021
*
*/
#include <iostream>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#define MESSAGE_LEN 100
int main(int argc, char *argv[])
{
int ret = -1;
int sock_fd;
struct sockaddr_in serv_addr, client_addr;
char recv_buf[MESSAGE_LEN] = {0,};
// create socket
sock_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sock_fd == -1)
{
std::cout << "Failed to create socket!" << std::endl;
exit(EXIT_FAILURE);
}
// create address and bind socket
memset(&serv_addr, 0, sizeof(struct sockaddr_in));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(19998);
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
ret = bind(sock_fd, (sockaddr *)&serv_addr, sizeof(struct sockaddr_in));
if (ret == -1)
{
std::cout << "Failed to bind socket!" << std::endl;
exit(EXIT_FAILURE);
}
// start to receive and echo
for(;;)
{
memset(recv_buf, 0, sizeof(recv_buf));
memset(&client_addr, 0, sizeof(struct sockaddr_in));
socklen_t addr_size = sizeof(struct sockaddr_in);
ret = recvfrom(sock_fd, (void *)recv_buf, MESSAGE_LEN, 0,
(sockaddr *)&client_addr, &addr_size);
if (ret <= 0)
{
continue;
}
recv_buf[ret] = '\0';
std::cout << "recv: " << recv_buf << std::endl;
ret = sendto(sock_fd, (void *)recv_buf, MESSAGE_LEN,
0, (sockaddr *)&client_addr, addr_size);
if (ret <= 0)
{
continue;
}
}
close(sock_fd);
return 0;
}
注释:
- 第 33行通过 socket() 函数创建了一个套接字,参数 AF_INET 表示使用 IPv4 地址,SOCK_DGRAM 表示使用数据报格式套接字,IPPROTO_UDP 表示使用 UDP 协议。在 Linux 中,socket 也是一种文件,有文件描述符,可以使用 write() / read() 函数进行 I/O 操作。
- 第45行将套接字与本地回环地址的19998端口绑定,sockaddr_in结构体是ipv4的地址格式,而sockaddr结构体是通用地址格式,两者大小相同,但结构体内部的定义稍有不同,故在传参时要进行强制类型转换。
- 第60行接受来自客户端的消息,使用recvfrom是为了获得客户端的地址,recvfrom在收到消息后,会把消息中所包含的地址信息放到client_addr中,后面我们需要用这个地址回传信息。
吐槽
- 刚刚接触c/c++网络编程,不得不说涉及的这些库函数参数非常复杂多样,而且风格也并不统一,入手时非常痛苦。
- Linux的man手册真是神器,大部分的接口函数都有详细的说明,不过全是英文读起来还是有些许吃力,而目前的汉化手册维护不频繁,而且有很多函数都缺失了,不能不说是一个遗憾