目录
1. UDP客户端
核心函数
完整的UDP客户端程序
2. UDP服务端
核心函数
完整的UDP客户端程序
3. 总结
ssize_t sendto(int sockfd,
const void *buf,
size_t nbytes,
int flags,
socklen_t addrlen );
#include
#include
#include
#include
#include
#include
#include
int main(int argc, charchar *argv[])
{
unsigned short port ;
charchar *server_ip ;
if( argc > 1 ) // main函数传参,服务器ip地址
{
server_ip = argv[1];
}
if( argc > 2 ) // main函数传参,服务器端口
{
port = atoi(argv[2]);
}
int sockfd;
sockfd = socket(AF_INET, SOCK_DGRAM, 0); //创建UDP套接字
if(sockfd < 0)
{
perror("socket");
exit(-1);
}
// 构造套接字地址 这个结构体有三个参数:套接字域,ip,port
struct sockaddr_in dest_addr;
bzero(&dest_addr, sizeof(dest_addr)); // 清空内容
dest_addr.sin_family = AF_INET; // ipv4
dest_addr.sin_port = htons(port); // 端口转换
inet_pton(AF_INET, server_ip, &dest_addr.sin_addr); // ip地址转换
printf("send data to UDP server %s:%d!\n", server_ip, port);
while(1)
{
char send_buf[512] = "";
fgets(send_buf, sizeof(send_buf), stdin);//获取输入
send_buf[strlen(send_buf)-1] = '\0';
//发送数据
int len = sendto(sockfd, send_buf, strlen(send_buf), 0, (struct sockaddr*)&dest_addr, sizeof(dest_addr));
printf("len = %d\n", len);
}
close(sockfd);
return 0;
}
接收端使用 bind() 函数,来完成地址结构与 socket 套接字的绑定,这样 ip、port 就固定了
int bind( int sockfd,
const struct sockaddr *myaddr,
socklen_t addrlen );
recvfrom方法接收 UDP 数据,并将源地址信息保存在 from 指向的结构中
ssize_t recvfrom( int sockfd,
void *buf,
size_t nbytes,
int flags,
struct sockaddr *from,
socklen_t *addrlen );
参数的含义,可以参考UDP客户顿的sendto方法:
#include
#include
#include
#include
#include
#include
#include
int main(int argc, charchar *argv[])
{
unsigned short port ; // 本地端口
if(argc > 1)
{
port = atoi(argv[1]);
}
int sockfd;
sockfd = socket(AF_INET, SOCK_DGRAM, 0); // 创建套接字
if(sockfd < 0)
{
perror("socket");
exit(-1);
}
// 构造本地网络地址的结构体 sockaddr_in
struct sockaddr_in my_addr;
bzero(&my_addr, sizeof(my_addr)); // 清空结构体内容
my_addr.sin_family = AF_INET; // ipv4
my_addr.sin_port = htons(port); // 端口转换
my_addr.sin_addr.s_addr = htonl(INADDR_ANY); // 绑定网卡所有ip地址,INADDR_ANY为通配地址,值为0
printf("Binding server to port %d\n", port);
int err_log;
//将套接字绑定到本地网络地址结构体上
err_log = bind(sockfd, (struct sockaddr*)&my_addr, sizeof(my_addr));
if(err_log != 0)
{
perror("bind");
close(sockfd);
exit(-1);
}
printf("receive data...\n");
while(1)
{
int recv_len;
char recv_buf[512] = "";
struct sockaddr_in client_addr;
char cli_ip[INET_ADDRSTRLEN] = "";//INET_ADDRSTRLEN=16
socklen_t cliaddr_len = sizeof(client_addr);
// 接受数据
recv_len = recvfrom(sockfd, recv_buf, sizeof(recv_buf), 0, (struct sockaddr*)&client_addr, &cliaddr_len);
inet_ntop(AF_INET, &client_addr.sin_addr, cli_ip, INET_ADDRSTRLEN);
printf("\nip:%s ,port:%d\n",cli_ip, ntohs(client_addr.sin_port));
printf("data(%d):%s\n",recv_len,recv_buf);
}
close(sockfd);
return 0;
}
UDP服务端编程分5步:
创建 UDP socket套接字,用socket函数。
设置socket的属性,用setsockopt()函数,(可选)
往socket绑定包含 IP信息,地址信息的 struct sockaddr_in(IPv4)结构体。用bind()函数
循环接收消息,用recvfrom()函数
关闭socket套接字
UDP客户端编程分:
创建 UDP socket套接字,用socket函数。
用sendto()函数往指定的IP,地址发送信息。