赞
踩
传输层协议:UDP(user Datagram protocol)<用户数据报协议>
UDP的优缺点:
优点:(1):具有高效率的数据传输的特性。
(2):不用其他函数编写,就能够实现多客户端发送至服务端。
缺点:面向一种无连接的传输层协议,它不能够保证可靠性通信,可能会造成数据丢失,数据失序,数据重复发送等问题。
UDP适用场合:
UDP实现客户端与服务端的通信步骤:
创建客户端步骤:
(1):创建UDP套接字。 socket()函数;成功:返回非负套接字描述符,失败:返回-1。
(2):设置对方的ip地址和端口号。
(3):发送消息。 sendto()函数; 成功:返回实际收到的字节数,失败:返回-1.
(4):关闭socket的对象 。close()函数
创建服务端步骤:
(1):创建UDP套接字。 socket()函数;成功:返回非负套接字描述符,失败:返回-1。
(2):绑定自己的ip地址和端口号。bink()函数 ;成功:返回0;失败:返回-1.
(3):接受收数据。 recvfrom()函数 成功:返回实际接受的字节数。失败:返回-1.
(4):关闭socket的对象 。close()函数
UDP实现客户端与服务端的通信的完整代码:
客户端代码:********************************************************
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
int main(int argc,char *argv[])
{
if(argc < 3)
{
printf("pease enter IP & port\n");
return -1;
}
/*
* UDP_socket是socket函数的返回值。
*AF_INET是socket函数的第一个传入值。代表IPv4协议
*SOCK_DGRAM是socket函数的第二个传入值。代表数据报套接字。
*0是socket函数的第三个传入值。一般都是0。
*/
//创建套接字
int UDP_socket = socket(AF_INET,SOCK_DGRAM,0);
if(UDP_socket < 0)
{
perror("socket error!");
return -1;
}
printf("socket ok!\n");
//设置对方的ip和端口号
//sockaddr_in系统通用结构体,也是存储ip,端口号等信息的专属结构体
struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = htons(atoi(argv[2]));
server.sin_addr.s_addr = inet_addr(argv[1]);
//发送数据
char buf[50] = {'\0'};
while(1)
{
printf("send:");
//fgets()函数是标准IO从键盘输入数据
fgets(buf,sizeof(buf),stdin);
/*解释函数sendto
*UDP_socket是sendto发送函数的第一个传入值,表示套接字描述符
*buf是sendto发送函数的第二个传入值,表示发送缓冲区首地址
*strlen(buf)是sendto发送函数的第三个传入值,表示发送数据的长度
*(struct sockaddr*)这表示强制类型转换
*(struct sockaddr*)&server 是sendto发送函数的第五个传入值。表示接受方套接字的ip地址 和端口号
*sizeof(server) 是sendto 发送函数的第六个传入值。表示地址的长度。
*/
sendto(UDP_socket,buf,strlen(buf),0,(struct sockaddr*)&server,sizeof(server));
}
//关闭socket的对象UDP_socket.
close(UDP_socket);
return 0;
}
************************************************************************************
服务端代码:*******************************************************************
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
int main(int argc,char *argv[])
{
if(argc < 2)
{
perror("please enter port!");
return -1;
}
/*
* UDP_socket是socket函数的返回值。
*AF_INET是socket函数的第一个传入值。代表IPv4协议
*SOCK_DGRAM是socket函数的第二个传入值。代表数据报套接字。
*0是socket函数的第三个传入值。一般都是0。
*/
//创建套接字
int UDP_socket = socket(AF_INET,SOCK_DGRAM,0);
if(UDP_socket < 0)
{
perror("socket error!");
return -1;
}
printf("socket ok!\n");
//设置自己的ip和端口号
//sockaddr_in系统通用结构体,也是存储ip,端口号等信息的专属结构体
struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = htons(atoi(argv[1]));
//系统自动自动获取ip地址
server.sin_addr.s_addr = INADDR_ANY;
//进行与客户端绑定
if(bind(UDP_socket,(struct sockaddr*)&server,sizeof(server))<0)
{
perror("bink error!");
return -1;
}
printf("bink ok!\n");
struct sockaddr_in src;
int len = sizeof(src);
char buf[50] = {'\0'};
while(1)
{
//每一次清空buf缓冲区的空间
memset(buf,0,sizeof(buf));
/*
* UDP_socket是recvfrom接受数据函数的第一个传入值,表示套接字描述符
*buf是recvfrom接受函数数据的第二个传入值,表示存放接受数据的缓存区
*strlen(buf)是recvfrom接受数据函数的第三个传入值,表示接受数据的长度
*(struct sockaddr*)这表示强制类型转换
*(struct sockaddr*)&server 是recvfrom发送函数的第五个传入值。表示接受方套接字的ip地 址 和端口号
*sizeof(server) 是recvfrom 接受数据函数的第六个传入值。表示地址的长度。
*/
recvfrom(UDP_socket,buf,sizeof(buf),0,(struct sockaddr*)&src,&len);
printf("recv:ip = %s port = %d %s\n",inet_ntoa(src.sin_addr),ntohs(src.sin_port),buf);
}
//关闭socket的对象UDP_socket.
close(UDP_socket);
return 0;
}
*****************************************************************************
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。