Linux关于socket(深入UDP与TCP区别)

socket之数据报套接字(UDP)

数据报套接字(SOCK_DGRAM) 数据报套接字定义了一种无连接的服务,数据通过相互独立的报文进行传输,是无序的,并且不保证可靠,无差错。使用数据报协议UDP协议。

socket之UDP实现

udp没有服务器和客户端的概念,但是我们为了和前一篇文章《Linux关于socket(TCP实现C/S)》相结合,进行总结TCP和UDP的区别,我们用代码实现UDP的服务端和客户端。

实现代码前,我们要知道UDP的写入是用sendto,读出使用recvfrom.而TCP读的话可以用read,send,写的话用recv,write

UDP不用实现TCP服务端的listen,accept,和客户端的connect,它直接创建完就可以使用,所以代码比较简洁。

以下是服务端代码

#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <sys/types.h>  
#include <sys/wait.h>
#include <sys/socket.h>  
#include <netinet/in.h> /* for struct sockaddr_in*/  
#include <sys/errno.h>  
#include <signal.h>  

//关于服务器udp的socket
void error_exit(char *name)
{
   perror(name);
   exit(-1);
}
int main(int argc,char *argv[])
{
   int sockfd=socket(AF_INET,SOCK_DGRAM,0);
   if(sockfd<0)
   {
        error_exit("create error");
   }
   //绑定地址(ip和端口号)
   struct sockaddr_in svraddr;
   memset(&svraddr,0,sizeof(svraddr));
   svraddr.sin_family=AF_INET;
   svraddr.sin_addr.s_addr=INADDR_ANY;
   //svraddr.sin_addr.s_addr=inet_addr("127.0.0.1");第二种写法
   svraddr.sin_port=htons(5555);
   int ret=bind(sockfd,(struct sockaddr*)&svraddr,sizeof(svraddr));
   if(ret<0)
   {
      error_exit("bind error");
   }
   char buf[1024]={0};
   struct sockaddr_in removeaddr;
   int addrlen=sizeof(removeaddr);
   while(1)
   {
       memset(buf,0,1024);
       int rdsize= recvfrom(sockfd,buf,1024,0,(struct sockaddr*)&removeaddr,&addrlen);
       if(rdsize>0)
       {
            printf("read data %s\n",buf);
       }
   }
   return 0;
}

以下是客服端代码:

#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <sys/types.h>  
#include <sys/wait.h>
#include <sys/socket.h>  
#include <netinet/in.h> /* for struct sockaddr_in*/  
#include <sys/errno.h>  
#include <signal.h>  


//关于客户端udp的socket
void error_exit(char *name)
{
   perror(name);
   exit(-1);
}
int main(int argc,char *argv[])
{
   int sockfd=socket(AF_INET,SOCK_DGRAM,0);
   if(sockfd<0)
   {
        error_exit("create error");
   }
   struct sockaddr_in svraddr;
   memset(&svraddr,0,sizeof(svraddr));
   svraddr.sin_addr.s_addr=inet_addr("127.0.0.1");
   svraddr.sin_port= htons(5555);
   svraddr.sin_family=AF_INET;
   int wdsize=sendto(sockfd,"helloworld",strlen("helloworld"),0,(struct sockaddr*)&svraddr,sizeof(svraddr));
   wdsize=sendto(sockfd,"helloworld",strlen("helloworld"),0,(struct sockaddr*)&svraddr,sizeof(svraddr));
   wdsize=sendto(sockfd,"helloworld",strlen("helloworld"),0,(struct sockaddr*)&svraddr,sizeof(svraddr)); 
   printf("write size%d\n",wdsize);
   return 0;
}

以上代码和上一篇关于TCP的实现方法差不多,实际更简洁(UDP实现起来更简单)

为了看出和TCP的区别,我们同样写入三次helloworld

以下是先执行服务器,在等待中

执行客服端,写入进去

切换到服务器,读到字符串

通过读到的字符串,我们可以清晰看到helloworld是一次次读出来,和TCP的连续读出不一样,这就是UDP的特点就是不粘包。

总结:

TCP 有连接,会粘包,数据不会丢失,流式套接字

UDP 无连接,不会粘包,数据会丢失,报文套接字

猜你喜欢

转载自blog.csdn.net/Gaodes/article/details/82795709