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;
}
相關文章
相關標籤/搜索