UDP网络程序采用的通信模型与TCP网络程序模型有很大的不同,具体见图7-4所示。
UDP服务器首先进行初始化操作:调用函数socket创建一个数据报类型的套接字,函数bind将这个套接字与服务器的公认地址绑定在一起。然后调用函数recvfrom接收UDP客户机的数据报。UDP客户机首先调用函数socket创建一个数据报套接字,然后调用函数sendto向服务器发送数据报。在结束通信后,客户机调用close关闭UDP套接字,服务器继续使用这个UDP套接字接收其它客户机的数据报。
下面我们就学习一下图7-4中的一些函数用法。Socket函数的用法在上节已经介绍了,这里就不在叙述。
数据发送函数sendto的原型为:
#include
#include
int sendto(int sockfd,const void *msg,int len,unsigned int flags,const struct sockaddr *to,int tolen);
该函数比send()函数多了两个参数:to表示目的机的IP地址和端口号;tolen为地址长度。Sendto函数也返回实际发送的数据字节长度,出现错误时返回-1。
数据接收函数recvfrom的原型为:
#include
#include
int recvfrom(int sockfd,void *buf,int len,unsigned int flags,struct sockaddr *from,int *fromlen);
参数from保存源机的IP地址和端口号;fromlen为此地址的长度。当recvfrom()返回时,fromlen包含实际存入from中的数据字节数,出现错误时返回-1。
下面我们就具体编写一个简单的基于UDP协议的服务器/客户端程序
服务器端程序server.c
/*************本程序用于创建服务端程序*****************/
#include
#include
#include
#include
#include
#define MYPORT 8866 /*定义端口为8866*/
#define MAX_MSG_SIZE 1024
int main(void)
{
int sockfd,n,addrlen;
struct sockaddr_in server_addr; /*服务器地址信息*/
struct sockaddr_in client_addr; /*客户端地址信息*/
char buffer[MAX_MSG_SIZE];
sockfd=socket(AF_INET,SOCK_DGRAM,0); /*创建数据报套接字*/
if(sockfd
{
printf("Socket Error:%s\n",strerror(errno));
exit(1);
}
/* 服务器端填充 sockaddr_in结构 */
bzero(&server_addr,sizeof(struct sockaddr_in));
server_addr.sin_family=AF_INET;
server_addr.sin_addr.s_addr=htonl(INADDR_ANY);
server_addr.sin_port=htons(MYPORT);
/*绑定套接字*/
if(bind(sockfd,(struct sockaddr *)&server_addr,sizeof(struct sockaddr))
{
printf("Bind Error:%s\n",strerror(errno));
exit(1);
}
addrlen=sizeof(struct sockaddr);
printf(“The server is waiting datas:\n”);
/* 接收客户端数据报,返回的为接收到的字节数 */
n=recvfrom(sockfd,buffer,MAX_MSG_SIZE,0,
(struct sockaddr *)&client_addr,&addrlen);
buffer[n]='\0';
printf("Got packer form %s\npacket contains:%s\n",
inet_ntoa(client_addr.sin_addr),buffer);
close(sockfd);
}
客户端程序client.c
#include
#include
#include
#include
#include
#include
#include
#include
#define MAX_BUF_SIZE 1024
#define MYPORT 8866 /*定义端口为8866*/
int main(int argc,char *argv[])
{
int sockfd,n;
struct sockaddr_in server_addr;
struct hostent *host;
char buffer[MAX_BUF_SIZE];
if(argc!=2)
{
printf("Usage:%s server_ip server_port\n",argv[0]);
exit(1);
}
/*gethostbyname可通过名称得到主机的IP地址*/
host=gethostbyname(argv[1]);
/*创建套接字*/
sockfd=socket(AF_INET,SOCK_DGRAM,0);
if(sockfd
{
printf("Socket Error:%s\n",strerror(errno));
exit(1);
}
/* 填充服务端的资料 */
bzero(&server_addr,sizeof(struct sockaddr_in));
server_addr.sin_family=AF_INET;
server_addr.sin_port=htons(MYPORT);
server_addr.sin_addr=*((struct in_addr *)host->h_addr);
printf("Please input some characters:\n");
scanf("%s",buffer);
/*向服务器端发送数据报*/
n=sendto(sockfd,buffer,strlen(buffer),0,
(struct sockaddr *)&server_addr,sizeof(struct sockaddr));
printf("sent %d bytes to %s\n",n,inet_ntoa(server_addr.sin_addr));
close(sockfd);
return 0;
}
Makefile文件的编写
all:server client
server:server.c
gcc –o server server.c
client:client.c
gcc –o client client.c
clean:
rm –f server
rm –f client
编译运行:
运行make后会产生两个程序server(服务器端)和client(客户端)。先运行./server,这时屏幕显示“The server is waiting datas:”,然后进入等待状态。屏幕显示如下:
./server
The server is waiting datas:
然后在本机打开另外一个终端,运行./client localhost,表明此客户端是相位于本机的服务器发送数据报,这时屏幕显示如下:
./client localhost
Please input some characters:
Abcdefghijk
sent 11 bytes to 127.0.0.1
这时,运行服务器程序的终端会显示:
Got packer form 127.0.0.1 packet contains: Abcdefghijk
转载:点击打开链接