UDP通信模型
UDP服务器端代码实现
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 1234
#define MAXDATASIZE 100
main(){
int sockfd,num;
struct sockaddr_in server;
struct sockaddr_in client;
socklen_t len;
char buf[MAXDATASIZE];
if((sockfd=socket(AF_INET,SOCK_DGRAM,0))==-1){
perror("Creating socket failed.");
exit(1);
}
bzero(&server,sizeof(server));
server.sin_family=AF_INET;
server.sin_port=htons(PORT);
server.sin_addr.s_addr=htonl(INADDR_ANY);
if(bind(sockfd,(struct sockaddr *)&server,sizeof(server))==-1){
perror("Bind() error");
exit(1);
}
len=sizeof(client);
while(1){
num=recvfrom(sockfd,buf,MAXDATASIZE,0,(struct sockaddr*)&client,&len);
if(num<0){
perror("recvfrom() error\n");
exit(1);
}
buf[num]='\0';
printf("You got a message <%s> from cient.\nIt's ip is %s,port is %d.\n",buf,inet_ntoa(client.sin_addr),htons(client.sin_port));
sendto(sockfd,"Welcome\n",8,0,(struct sockaddr *)&client,len);
if(!strcmp(buf,"bye"))
break;
}
close(sockfd);
}
UDP客户端代码实现
/****************************************
* UDP 客户端实现的步骤
*(1)使用socket()函数创建套接字
*(2)发送数据请求给服务器
*(3)等待接受服务器的数据应答
*(4)关闭套接字
*
******************************************/
//头文件包含
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <netdb.h>
//宏定义
#define PORT 1234 //指定使用的端口号
#define MAXDATASIZE 100 //定义用于存储数据的缓冲区大小
/********************************
*在main函数中有两个参数:
*argc 指命令行中参数的个数
*argv[] 指向字符串
********************************/
int main(int argc,char *argv[]){
int sockfd,num; //sockfd是sock file descriptor的缩写,是套接字函数返回的套接字描述符
socklen_t len;
char buf[MAXDATASIZE]; //定义用于存储数据的缓冲区的大小
struct hostent *he; //定义指向hostent结构体的指针
struct sockaddr_in server,peer; //定义结构体变量sockaddr_in变量
if(argc!=3){
printf("Usage:%s<IP Address><message>\n",argv[0]);
exit(1);
}
/*************************************************
* 检查用户的输入,如果输入不正确则提示错误信息
**************************************************/
if((he=gethostbyname(argv[1]))==NULL){
printf("gethostbyname() error\n");
exit(1);
}
/******************************************************************
*功能说明:调用socket函数产生套接字描述符
*函 数:int socket(int family,int type,int protocol)
*参数说明:family 指明协议簇,确定socket使用的协议类型,其值常为:
* (1)AF_INET :IPV4协议
* (2)AF_INET6:IPV6协议
* (3)AF_ROUTE:路由套接口
* type 指明产生套接字的类型,其值常为:
(1)SOCK_STREAM:字节流套接口,TCP使用的是这种形式
(2)SOCK_DGRAME:数据报套接口,UDP使用的是这种形式
(3)SOCK_RAW:原始套接口
Protocol 协议标志,一般在调用socket函数时将其置为0,当如果是原始套接字,就需要为protocol指定一个常值
*返回值说明:如果函数调用失败返回 “-1”,如果调用成功,将返回一个小的非负的整数值
*********************************************************************/
if((sockfd=socket(AF_INET,SOCK_DGRAM,0))==-1){
printf("socket() error\n");
exit(1);
}
/*******************************************************
*功能说明:初始化服务器的地址结构,并为地址结构赋值
*函数说明:extern void bzero(void *s,int n);
*参数说明:s 要置零的数据的起始地址
* n 要置零的数据字节个数
*******************************************************/
bzero(&server,sizeof(server)); //将套接字地址结构server设置初始值为0
server.sin_family=AF_INET; //设置使用的协议簇类型
server.sin_port=htons(PORT); //设置使用的端口,并且将主机字节序转换为网络字节序
server.sin_addr=*((struct in_addr *)he->h_addr);
/******************************************
*功能说明:将用户从命令行输入的消息发送到服务器端
*函数说明:ssize_t sendto(int sockfd,const void * buf,size_t len,int flags,const struct sockaddr *to ,int addrlen);
*参数说明: sockfd 套接字描述符
* buf 指向一个用于接收信息的数据缓冲区
* len 指明接受数据缓冲区的大小
* flag 传输控制标识符
* to 套接字的地址结构
* addrlen 协议地址的大小
*********************************************/
sendto(sockfd,argv[2],strlen(argv[2]),0,(struct sockaddr *)&server,sizeof(server));
len=sizeof(server);
while(1){
if((num=recvfrom(sockfd,buf,MAXDATASIZE,0,(struct sockaddr*)&peer,&len))==-1){
printf("recvfrom() error\n");
exit(1);
}
if(len!=sizeof(server)||memcmp((const void *)&server,(const void *)&peer,len)!=0){
printf("Receive message from other server.\n");
continue;
}
buf[num]='\0';
printf("Server Message:%s.\n",buf);
break;
}
close(sockfd);
}
运行示例