服务器流程:
创建用户数据报套接字
填充服务器网络信息结构体
将套接字与服务器网络信息结构体绑定
收发数据 sendto / recvfrom
关闭套接字
客户端流程:
创建用户数据报套接字
填充服务器网络信息结构体
收发数据 sendto / recvfrom
关闭套接字
运行结果图
service.c
#include <head.h>
int main(int argc, const char *argv[])
{
// 入参合理性检查
if (3 != argc)
{
printf("usage error:%s <ip> <port>...\n", argv[0]);
exit(-1);
}
// 创建套接字
int sockfd;
if (-1 == (sockfd = socket(AF_INET, SOCK_DGRAM, 0)))
{
PRINT_ERR("socket error");
}
// 填充服务器网络信息结构体
struct sockaddr_in serveraddr;
socklen_t serveraddr_len = sizeof(serveraddr);
memset(&serveraddr, 0, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
serveraddr.sin_port = htons(atoi(argv[2]));
// 将套接字和服务器网络信息结构体绑定
if (-1 == bind(sockfd, (struct sockaddr *)&serveraddr, serveraddr_len))
{
PRINT_ERR("bind error");
}
// 定义结构体保存客户端信息
// 如果不保存客户端信息网络信息结构体 那么服务器收数据没问题
// 但是服务器就没法给客户端回复数据了,因为sendto的后两个参数没法填写
// 如果想回复数据给客户端,就必须保存客户端的网络信息结构体
struct sockaddr_in clientaddr;
socklen_t clientaddr_len = sizeof(clientaddr);
// 收发数据
char buff[128] = {0};
while (1)
{
memset(buff, 0, sizeof(buff));
if (-1 == recvfrom(sockfd, buff, sizeof(buff), 0, (struct sockaddr *)&clientaddr, &clientaddr_len))
{
PRINT_ERR("recv from");
}
buff[strlen(buff) - 1] = '\0';
printf("收到客户端[%s:%d]发来的数据[%s]\n", inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port), buff);
// 组装应答消息
strcat(buff, "----拼接应答消息");
if (-1 == sendto(sockfd, buff, sizeof(buff), 0, (struct sockaddr *)&clientaddr, clientaddr_len))
{
PRINT_ERR("sento error");
}
}
close(sockfd);
return 0;
}
client.c
#include <head.h>
int main(int argc, const char *argv[])
{
// 入参合理性检查
if (3 != argc)
{
printf("usage error:%s <ip> <port>", argv[0]);
exit(-1);
}
// 创建套接字
int sockfd;
if (-1 == (sockfd = socket(AF_INET, SOCK_DGRAM, 0)))
{
PRINT_ERR("socket error");
}
// 填充服务器网络信息结构体
struct sockaddr_in serveraddr;
socklen_t serveraddr_len = sizeof(serveraddr);
memset(&serveraddr, 0, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(atoi(argv[2]));
serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
// 收发数据
char buff[128] = {0};
while (1)
{
memset(buff, 0, sizeof(buff));
printf("请输入:");
fgets(buff, sizeof(buff), stdin);
if (-1 == sendto(sockfd, buff, sizeof(buff), 0, (struct sockaddr *)&serveraddr, serveraddr_len))
{
PRINT_ERR("sento error");
}
// 接收应答消息
// 此处不用再填写服务器的信息 因为上一步的sendto已经填写了 serveraddr没改变属于同一个
if (-1 == recvfrom(sockfd, buff, sizeof(buff), 0, NULL, NULL))
{
PRINT_ERR("recvfrom error");
}
printf("收到的应答消息:%s\n", buff);
}
close(sockfd);
return 0;
}
Makefile
all:service client
service:service.o
gcc $^ -o $@
client:client.o
gcc $^ -o $@
%.o:%.c
gcc -c $^ -o $@
clean:
rm *.o service client