qfedu-network-advanced-level/day2/n7.c

70 lines
2.1 KiB
C

#include <stdio.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char const *argv[])
{
int sfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sfd < 0)
{
perror("socket");
return -1;
}
// 1. 绑定本地 ip 和端口号
struct sockaddr_in addr; // sockaddr_in 结构体对象
bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(8000); // 当前 Linux 进程的端口号
addr.sin_addr.s_addr = htonl(INADDR_ANY); // INADDR_ANY 任意连接的 ip 可用
// inet_pton(AF_INET, "192.168.31.128", &addr.sin_addr.s_addr);
if (bind(sfd, (struct sockaddr *)&addr, sizeof(addr)) != 0) // 绑定
{
perror("bind");
}
else
{
printf("bind success\n");
// 接收数据
char buf[128] = ""; // 接收数据的空间
struct sockaddr_in src_addr; // 数据来源的地址
socklen_t addr_len;
while (1)
{
// 重置数据
bzero(&src_addr, sizeof(src_addr));
bzero(buf, 128);
// 接收数据,如果数据未到达,则会阻塞,直到数据到达为止
socklen_t addr_len = sizeof(src_addr);
ssize_t len = recvfrom(sfd, buf, 128, 0, (struct sockaddr *)&src_addr, &addr_len);
if (len < 0)
{
perror("recvfrom");
break;
}
char src_ip[16];
int src_port = ntohs(src_addr.sin_port); // 将网络字节序转化为主机字节序
inet_ntop(AF_INET, &src_addr.sin_addr.s_addr, src_ip, 16); // 从 src_addr 取 ip 并转化为字符串赋值给 src_ip
printf("从 %s:%d 位置接受到的数据(%ld Bytes): %s\n", src_ip, src_port, len, buf);
char buf2[1280];
sprintf(buf2, "返回: %s\n", buf);
// 回一句消息
sendto(sfd, buf2, strlen(buf2), 0, (struct sockaddr *)&src_addr, addr_len);
}
}
close(sfd);
return 0;
}