基于udp的服务器和客户端编程

TCP与UDP的区别:

  • 基于连接与无连接
  • 对系统资源的要求(TCP较多,UDP较少)
  • UDP程序结构简单
  • 流模式与数据报模式
  • TCP保证数据的正确性,UDP可能会丢包,TCP保证数据顺序,UDP不保证。

TCP与UDP的编程区别:

  • socket()的参数不同
  • UDP Server不需要调用listen和accept
  • UDP收发数据用sendto/recvfrom函数 
  • TCP:地址信息在connect/accept时确定 
  • UDP:在sendto/recvfrom函数中每次均 需指定地址信息

UDP编程步骤:

  • 创建一个socket,用函数socket()
  • 绑定IP地址、端口等信息到socket上,用函数bind()
  • 循环接收数据,用函数recvfrom()
  • 关闭网络连接

一.创建套接字:函数socket()

    1.所包含的头文件

#include 
#include 

   2.函数原型

 int socket(int domain, int type, int protocol);
  • domain:指定协议族,比如TCP/IP协议PF_INET PF_INET6 
  • type:指定服务器类型,SOCK_STREAM   SOCK_UGRAM
  • protocal:具体协议,通常默认为0

   3.函数返回值:成功则返回socket文件描述符,失败则返回-1,设置errno

   4.代码

int socketfd = socket(AF_INET,SOCK_DGRAM,0);
if(socketfd == -1)
{
    perror("socket");
    return -1;
}

二.绑定IP地址、端口等信息到socket上,用函数bind()

    1.所包含的头文件

#include 
#include 

   2.函数原型

 int  bind(int  sockfd,  const  struct  sockaddr *my_addr,socklen_t addrlen);
  • sockfd:socket文件描述符
  • addr:指定socket绑定的地址
  • addrlen:socket地址长度

   3.函数返回值:成功则返回0,失败则返回-1,设置errno

   4.代码

int ret;
int socketfd;

struct sockaddr_in server;

socketfd = socket(AF_INET,SOCK_DGRAM,0);
if(socketfd == -1)
{
	perror("socket");
	return -1;
}

ret = bind(socketfd,(struct sockaddr *)&server,sizeof(server));
if(ret == -1)
{
	perror("bind");
	return -1;
}

三. 循环接收数据,用函数recvfrom()

   1.所包含的头文件

 #include 
 #include 

   2.函数原型

 ssize_t recvfrom(int s, void *buf, size_t len, int flags,struct sockaddr *from, socklen_t *fromlen);
  • sockfd:需要读写数据的sockfd
  • buf     :读写缓冲区的指针
  • len     :读写缓冲区的大小
  • flags  :通常设置为0

   因为UDP没有连接的概念,因此每次读写数据都需要获取发送/接受端的socket地址,addrlen指定地址长度,flags参数同TCP

    3.代码

while(1)
{
	rev_len = recvfrom(socketfd,buf,sizeof(buf),0,(struct sockadd *)&client,&len);
	if(rev_len < 0)
	{
		perror("recv");
		return -1;
	}
	printf("buf = %s\n",buf);
	memset(buf,0,100);
}	

   四:UDP服务器编程源代码

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 


#define PORT 7891
#define BUF_LEN 100

int main(int argc,char ** argv)
{	
	int socketfd;
	int rev_len;
	int ret;
	
	char buf[BUF_LEN] = {0};
	int len = sizeof(struct sockaddr_in);

	struct sockaddr_in server;
	struct sockaddr_in client;
	
	socketfd = socket(AF_INET,SOCK_DGRAM,0);
	if(socketfd == -1)
	{
		perror("socket");
		return -1;
	}

	bzero(&server,sizeof(server));
	server.sin_family = AF_INET;
	server.sin_port = htons(PORT);
	server.sin_addr.s_addr = inet_addr(argv[1]);

	ret = bind(socketfd,(struct sockaddr *)&server,sizeof(server));
	if(ret == -1)
	{
		perror("bind");
		return -1;
	}

	
	while(1)
	{
		rev_len = recvfrom(socketfd,buf,sizeof(buf),0,(struct sockaddr *)&client,&len);
		if(rev_len < 0)
		{
			perror("recv");
			return -1;
		}
		printf("buf = %s\n",buf);
		memset(buf,0,100);
	}	

	close(socketfd);
	
	return 0;
}

五:UDP客户端编程

 写数据用sendto()函数

   1.所含头文件

 #include 
 #include 

 

   2.函数原型

 ssize_t sendto(int s, const void *buf,  size_t  len,  int flags, const struct sockaddr *to, socklen_t tolen);

    参数参考recvfrom 

   3.udp客户端源代码

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define PORT 7891
#define MAX_LEN 100

int main(int argc,char ** argv)
{
	int socketfd;
	int send_len;
	int len = sizeof(struct sockaddr_in);
	char buf[MAX_LEN] = {0};

	struct sockaddr_in server_addr;

	socketfd = socket(AF_INET,SOCK_DGRAM,0);
	if(socketfd < 0)
	{
		perror("socket");
		return -1;
	}

	bzero(&server_addr,sizeof(server_addr));

    server_addr.sin_family  = AF_INET;
    server_addr.sin_port = htons(PORT);
    server_addr.sin_addr.s_addr =  inet_addr((const char *)argv[1]);

	while(1)
	{
		printf("请输入文字\n");
		scanf("%s",buf);
		send_len = sendto(socketfd,buf,MAX_LEN,0,(struct sockaddr *)&server_addr,len);	
	}

	close(socketfd);
	
	return 0;
}

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(基于udp的服务器和客户端编程)