分类: LINUX
2008-11-30 14:24:52
UDP服务器首先进行初始化操作:调用函数socket创建一个数据报类型的套接字,函数bind将这个套接字与服务器的公认地址绑定在一起。然后调用函数recvfrom接收UDP客户机的数据报。UDP客户机首先调用函数socket创建一个数据报套接字,然后调用函数sendto向服务器发送数据报。在结束通信后,客户机调用close关闭UDP套接字,服务器继续使用这个UDP套接字接收其它客户机的数据报。
下面我们就学习一下图7-4中的一些函数用法。Socket函数的用法在上节已经介绍了,这里就不在叙述。
数据发送函数sendto的原型为:
#include #include < sys/socket.h > 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 < sys/socket.h > 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<0) { 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))<0) { 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<0) { 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 |