计算机网络基于UDP的服务器和客户端

来源:互联网 发布:淘宝宅腐仓 编辑:程序博客网 时间:2024/05/22 01:37

UDP和TCP所不同的是,由于UDP是无连接的,所以就不用监听listen和accept这两个步骤,比起TCP 就显得简单了很多。另外,UDP当中收发数据,发的是数据报,收必须以数据报收回。

Userver.c

      #include <stdio.h>  
     #include <stdlib.h>  
     #include <unistd.h>  
     #include <string.h>  
     #include <sys/types.h>  
     #include <sys/socket.h>  
     #include <netinet/in.h>  
     #include <netdb.h>  
  
     #define PORT 1234  
     #define MAXDATASIZE 100  
  
     int main(int argc, char *argv[])  
     {  
     int sockfd, num;  
     char buf[MAXDATASIZE];  
  
     struct hostent *he;  
     struct sockaddr_in server,peer;  
  
     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);  
     }  
  
     if ((sockfd=socket(AF_INET, SOCK_DGRAM,0))==-1)  
     {  
     printf("socket() error\n");  
     exit(1);  
     }  
  
     bzero(&server,sizeof(server));  
     server.sin_family = AF_INET;  
     server.sin_port = htons(PORT);  
     server.sin_addr= *((struct in_addr *)he->h_addr);  
     sendto(sockfd, argv[2],strlen(argv[2]),0,(struct sockaddr *)&server,sizeof(server));  
     socklen_t  addrlen;  
     addrlen=sizeof(server);  
     while (1)  
     {  
     if((num=recvfrom(sockfd,buf,MAXDATASIZE,0,(struct sockaddr *)&peer,&addrlen))== -1)  
     {  
     printf("recvfrom() error\n");  
     exit(1);  
     }  
     if (addrlen != sizeof(server) ||memcmp((const void *)&server, (const void *)&peer,addrlen) != 0)  
     {  
     printf("Receive message from otherserver.\n");  
     continue;  
     }  
  
     buf[num]='\0';  
     printf("Server Message:%s\n",buf);  
     break;  
     }  
  
     close(sockfd);  
     }  




Uclient.c

#include<stdio.h>

#include<stdlib.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<string.h>
static void use(char* proc)
{
    printf("%s [server_ip][server_port]\n",proc);
}
int main(int argc,char* argv[])
{
    if(argc!=3)
    {
        use(argv[0]);
        return 1;
    }
    int sock =socket(AF_INET,SOCK_DGRAM,0) ;
    struct sockaddr_in peer;
    peer.sin_family = AF_INET;
    peer.sin_port = htons(atoi(argv[2]));
    peer.sin_addr.s_addr = inet_addr(argv[1]);
    char buf[1024];
    while(1)
    {
        printf("please enter#");
        fflush(stdout);
        ssize_t s = read(0,buf,sizeof(buf)-1);
        if(s>0)
        {
            ssize_t _s = sendto(sock,buf,strlen(buf),0,(struct sockaddr*)&peer,sizeof(peer));
          if(_s<0)
          {
            perror("sendto");
            return 2;
          }
        }
ssize_t r =recvfrom(sock,buf,sizeof(buf)-1,0,NULL,NULL);
        if(r<0)
        {
            perror("recvfrom");
            return 3;
        }
        else
        {
            printf("server echo#%s",buf);
        }
    }
    close(sock);
    return 0;

}

运行结果:


那么既然UDP是不可靠的,那怎么保证可靠性呢?

传输层无法保证数据的可靠传输,只能通过应用层来实现。实现的方式与TCP类似,只是实现不在传输层,实现转移到了应用层。

         实现确认机制、重传机制、窗口确认机制。

         如果你不利用Linux协议栈以及上层套接字,自己通过抓包和发包的方式去实现可靠性传输,那么必须实现如下功能:

         发送:包的分片、包确认、包的重发

         接收:包的调序、包的序号确认

         目前有如下开源程序利用udp实现了可靠的数据传输。分别为RUDP、RTP、UDT。



原创粉丝点击