#include <sys/types.h>
#include <sys/socket.h>
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *from, int *fromlen);
返回:大于0-成功接收数据长度;-1-出错;
UDP套接字使用无连接协议,因此必须使用recvfrom函数,指明源地址;本函数从(已连接)套接口上接收数据,并捕获数据发送源的地址。
flags是传输控制标志,其值定义如下:
0:常规操作,如同read()函数;
from 和 fromlen 是“数据源地址-长度”参数。
#include <sys/types.h>
#include <sys/socket.h>
ssize_t sendto(int sockfd, const void *msg, size_t len, int flags, const struct sockaddr *to, int tolen);
返回:大于0-成功发送数据长度;-1-出错;
UDP套接字使用无连接协议,因此必须使用sendto函数,指明目的地址;
flags是传输控制标志,其值定义如下:
0:常规操作,如同write()函数;
代码实战
/*udpclient.c*/
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include<stdlib.h>
#include<errno.h>
int main(int argc, char *argv[])
{
int fd;
struct sockaddr_in server,peer;
char rbuf[100];
socklen_t len;
int num;
if (argc !=3)
{
printf("Usage: %s <IP Address> <message>\n", argv[0]);
exit(1);
}
fd=socket(AF_INET, SOCK_DGRAM, 0);
if (fd==-1)
{
perror("socket");
exit(1);
}
bzero(&server,sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(1234);
server.sin_addr.s_addr = inet_addr(argv[1]);
//发送数据
num=sendto(fd,argv[2],strlen(argv[2]),0,(struct sockaddr *)&server,sizeof(server));
printf("client send %d bytes\n",num);
len=sizeof(server);
while(1)
{
//if(strncmp(argv[2],"bye",3)==0)
// break;
//接收数据
num=recvfrom(fd,rbuf,sizeof(rbuf),0,(struct sockaddr *)&peer,&len);
if(num==-1)
{
printf("recvfrom errno is %d\n",errno);
break;
}
rbuf[num]='\0';
//比较是否是服务器地址
// memcmp是比较内存区域buf1和buf2的前count个字节。该函数是按字节比较的。
if(len != sizeof(server) || memcmp(&server,&peer,len)!=0)
{
printf("message not from server!\n");
continue;
}
//输出信息
printf("server message:%s.\n",rbuf);
break;
}
close(fd);
}
/*udpserver.c*/
#include <sys/socket.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include<stdlib.h>
int main(void)
{
int sockfd;
struct sockaddr_in server,client;
int port = 1234;
int opt = SO_REUSEADDR;
int rt;
int addrlen;
char sendbuf[100];
char rbuf[100];
int num;
sockfd=socket(AF_INET,SOCK_DGRAM,0);
if(sockfd==-1)
{
perror("socket");
exit(1);
}
//避免出现地址已经使用的错误
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
bzero(&server,sizeof(server));
server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr("127.0.0.1"); //回送地址,指本地机,一般用来测试使用
server.sin_port = htons(port);
rt=bind(sockfd, (struct sockaddr *)& server, sizeof(server));
if (rt== -1)
{
perror("bind");
exit(1);
}
addrlen=sizeof(client);
while(1)
{ //接收客户端信息
num=recvfrom(sockfd,rbuf,sizeof(rbuf),0,(struct sockaddr *)&client,&addrlen);
if(num<0)
{
perror("recvfrom");
break;
}
rbuf[num]='\0';
//显示客户端信息,如果客户端发来bye则退出循环
printf("Got a message <%s> from client.\nIt's IP is %s,port is %d.\n", rbuf,inet_ntoa(client.sin_addr),ntohs(client.sin_port));
if(strcmp(rbuf,"bye")==0)
break;
//向客户端发送welcome
sprintf(sendbuf,"welcome!");
num=sendto(sockfd,sendbuf,strlen(sendbuf),0,(struct sockaddr *)&client,addrlen);
printf("server send %d bytes\n",num);
}
close(sockfd);
}