socket通讯——UDP

UDP基础知识

UDP(User Datagram Protocol,用户数据报协议)是一个简单的、面向数据报的无链接协议,提供了快速但不必定可靠的传输服务。编程

  UDP与TCP相比主要有如下区别。网络

    1.UDP速度比TCP快socket

      因为UDP不须要先与对方创建链接,也不须要传输确认,所以其数据传输速度比TCP快得多。ide

    2.UDP有消息边界函数

      使用UDP不须要考虑消息边界问题,使用上比TCP简单spa

    3.UDP能够一对多传输3d

      利用UDP可使用广播或组播的方式同时向子网上的全部客户发送信息。这一点也比TCP方便。指针

    4.UDP可靠性不如TCPrest

      与TCP不一样,UDP并不提供数据传送的保证机制。若是在从发送方到接收方的传递过程当中出现数据报的丢失,协议自己并不能作出任何检测或提示。所以,一般人们把UDP称为不可靠的传输协议。orm

    5.UDP不像TCP那样能保证有序传输

      UDP不能确保数据的发送和接收顺序。对于突发性的数据报,有可能会乱序。事实上,UDP的这种乱序性基本上不多出现,一般只会在网络很是拥挤的状况下才有可能发生

UDP编程

wKiom1eZzb2x5QBOAAGvfMmLOns092.png

 1)建立socket时,数据格式为:SOCK_DGRAM(数据块)

 2)数据收发用recvfrom和sendto

          ssize_t recvfrom(int socket,void *restrict buffer,size_t length,int flags,struct sockaddr * restrict address,socklen_t *restrict address_len);

           restrict:类型限定符,限定约束指针。代表该指针是访问这个数据队形的惟一的方式

            补充一点:

               void *memcpy( void * restrict dest ,const void * restrict src,sizi_t n) 这是一个颇有用的内存复制函数,因为两个参数都加了restrict限定,因此两块区域不能重叠,即 dest指针所指的区域,不能让别的指针来修改,即src的指针不能修改. 相对应的别一个函数 memmove(void *dest,const void * src,size_t)则能够重叠。

          socket:  已链接的套接字

          buffer:接收数据的缓冲区

          length:缓冲区长度

           flags  :调用操做方式

           address:指向装有源地址的缓冲区(传出型参数)

           address_len:指向源地址缓冲区的实际长度(传入传出型参数)

          ssize_t sendto(int socket,const void*buffer,size_t length,int flags,struct sockaddr* dest_addr,socklen_t len);

             socket:已链接套接字

             buffer:包含待发送数据的缓冲区

             length:buffer缓冲区数据的长度

             flags:调用方式标志位

             dest_addr:指向目的套接字的地址

           len:dest_addr所指地址的长度


代码:

server.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define SIZE 1024
int main(int argc,char *argv[])
{
  if(argc!=3)
  {
    printf("enter [IP],[PORT]\n");
  }
  int fd=socket(AF_INET,SOCK_DGRAM,0);
  if(fd<0)
  {
    perror(socket);
    return 1;
  }
  struct sockaddr_in local;
  int port=atoi(argv[2]);
  local.sin_family=AF_INET;
  local.sin_port=htons(port);
  local.sin_addr.s_addr=inet_addr(argv[1]);
  if(bind(fd,(struct socketaddr*)&local,sizeof(local))<0)
  {
    perror("bind");
    return 2;
  }
 struct sockaddr_in remote;
 socklen_t len=sizeof(remote);
  while(1)
  {
    char buf[SIZE];
    memset(buf,'\0',sizeof(buf));
    ssize_t _s=recvfrom(fd,buf,sizeof(buf)-1,0,(struct socketaddr *)&remote,&len);
    if(_s>0)
    {
      buf[_s]='\0';
      printf("client:[ip:%s][port:%d] %s",inet_ntoa(remote.sin_addr),ntohs(remote.sin_port));
    }
    else if(_s==0)
    {
      printf("read done..\n");
      break;
    }
    else{
      break;
    }
  }
  close(fd);
  return 0;
}

client.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(int argc,char *argv[])
{
  if(argc!=3)
  { 
    printf("[ip][port]\n");
    return 1;
  }
  int fd=socket(AF_INET,SOCK_DGRAM,0);
  if(fd<0)
  {
    perror("socket");
    return 2;
  }
  int port=atoi(argv[2]);
  struct sockaddr_in remote;
  remote.sin_family=AF_INET;
  remote.sin_port=htons(port);
  remote.sin_addr.s_addr=inet_addr(argv[1]);
  while(1)
  {
    char buf[1024];
    memset(buf,'\0',sizeof(buf)-1);
    ssize_t _ss=read(0,buf,sizeof(buf)-1);
     if(_s>0)
	{
		buf[_s]='\0';	
	}
    ssize_t _s=sendto(fd,buf,sizeof(buf)-1,0,(struct sockaddr *)&remote,sizeof(remote));
  }
  return 0;
}
相关文章
相关标签/搜索