Linux網路編程基礎之二--UDP

來源:互聯網
上載者:User

 

    我們在Linux網路編程基礎之一裡說了流socket和資料報socket的聯絡和區別。我們在這裡簡單說一下基於UDP協議的網路編程。
    兩個常用的函數
   int recvfrom(int sockfd,void *buf,int len,unsigned int flags,struct sockaddr * from int *fromlen)
   int sendto(int sockfd,const void *msg,int len,unsigned int flags,struct sockaddr *to int tolen)
其中sockfd,buf,len的意義和read,write一樣,分別表示通訊端描述符,發送或接收的緩衝區及大小.
recvfrom
負責從
sockfd接收資料,如果from不是NULL,那麼在from裡面儲存了資訊來源的情況,如果對資訊的來源不感興趣,可以將from和fromlen
設定為NULL.sendto負責向to發送資訊.此時在to裡面儲存了收資訊方的詳細資料.

下面是一個簡單的例子(選自Understanding Unix/Linux Programming):

伺服器端(接收資料報,dgrecv.c使用命令列傳過來的連接埠號碼建立socket,然後進入迴圈,接收和列印從用戶端發來的資料報):
/************************************************************************
 * dgrecv.c  - datagram receiver
 *           usage: dgrecv portnum
 *          action: listens at the specfied port and reports messages
 */

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define oops(m,x)  { perror(m);exit(x);}
/*輔助函數make_dgram_server和get_internet_address將在後面給出的檔案dgram.c中定義*/
int  make_dgram_server_socket(int);
int  get_internet_address(char *, int,  int *, struct sockaddr_in *);
void say_who_called(struct sockaddr_in *);

int main(int ac, char *av[])
{
 int port;   /* use this port  */
 int sock;   /* for this socket  */
 char buf[BUFSIZ];  /* to receive data here  */
 size_t msglen;   /* store its length here */
 struct  sockaddr_in   saddr; /* put sender's address here */
 socklen_t saddrlen;  /* and its length here  */
 
 if ( ac == 1 || (port = atoi(av[1])) <= 0 ){
  fprintf(stderr,"usage: dgrecv portnumber\n");
  exit(1);
 }

    /*  get a socket and assign it a port number */

 if( (sock = make_dgram_server_socket(port)) == -1 )
  oops("cannot make socket",2);

    /* receive messaages on that socket */

 saddrlen = sizeof(saddr);
 while( (msglen = recvfrom(sock,buf,BUFSIZ,0,
    (struct sockaddr *) &saddr,&saddrlen))>0 ) {
  buf[msglen] = '\0';
  printf("dgrecv: got a message: %s\n", buf);
  say_who_called(&saddr);
 }
 return 0;
}
void say_who_called(struct sockaddr_in *addrp)
{
 char host[BUFSIZ];
 int port;

 get_internet_address(host,BUFSIZ,&port,addrp);
 printf("  from: %s:%d\n", host, port);
}
用戶端(建立一個socket,然後用它發送訊息到以命令列參數傳入的特定的主機和連接埠號碼):
/*********************************************************************
 * dgsend.c  - datagram sender
 *           usage: dgsend hostname portnum "message"
 *          action: sends message to hostname:portnum
 */

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define oops(m,x)  { perror(m);exit(x);}

int make_dgram_client_socket();
int make_internet_address(char *,int, struct sockaddr_in *);

int main(int ac, char *av[])
{
 int sock;   /* use this socket to send */
 char *msg;   /* send this messag  */
 struct  sockaddr_in   saddr; /* put sender's address here */

 if ( ac != 4 ){
  fprintf(stderr,"usage: dgsend host port 'message'\n");
  exit(1);
 }
 msg = av[3];

    /* get a datagram socket */

 if( (sock = make_dgram_client_socket()) == -1 )
  oops("cannot make socket",2);

    /* combine hostname and portnumber of destination into an address */

 if ( make_internet_address(av[1], atoi(av[2]), &saddr) == -1 )
  oops("make addr",4);

    /* send a string through the socket to that address */

 if ( sendto(sock, msg, strlen(msg), 0,
    (struct sockaddr *)&saddr,sizeof(saddr)) == -1)
  oops("sendto failed", 3);
 return 0;
}

輔助函數
/***************************************************************
 * dgram.c
 * support functions for datagram based programs
 */

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <string.h>

#define   HOSTLEN  256

int make_internet_address();

int make_dgram_server_socket(int portnum)
{
 struct  sockaddr_in   saddr;   /* build our address here */
 char hostname[HOSTLEN];     /* address           */
 int sock_id;        /* the socket             */

 sock_id = socket(PF_INET, SOCK_DGRAM, 0);  /* get a socket */
 if ( sock_id == -1 ) return -1;

 /** build address and bind it to socket **/

 gethostname(hostname, HOSTLEN);         /* where am I ?         */
 make_internet_address(hostname, portnum, &saddr);

 if ( bind(sock_id, (struct sockaddr *)&saddr, sizeof(saddr)) != 0 )
        return -1;

 return sock_id;
}
int make_dgram_client_socket()
{
 return socket(PF_INET, SOCK_DGRAM, 0);
}

int make_internet_address(char *hostname, int port, struct sockaddr_in *addrp)
/*
 * constructor for an Internet socket address, uses hostname and port
 *   (host,port) -> *addrp
 */
{
 struct hostent *hp;

 bzero((void *)addrp, sizeof(struct sockaddr_in));
 hp = gethostbyname(hostname);
 if ( hp == NULL ) return -1;
 bcopy((void *)hp->h_addr, (void *)&addrp->sin_addr, hp->h_length);
 addrp->sin_port = htons(port);
 addrp->sin_family = AF_INET;
 return 0;
}

int get_internet_address(char *host, int len, int *portp, struct sockaddr_in *addrp)
/*
 * extracts host and port from an internet socket address
 *   *addrp -> (host,port)
 */
{
 strncpy(host, inet_ntoa(addrp->sin_addr), len );
 *portp = ntohs(addrp->sin_port);
 return 0;
}

Makefile如下:
all:dgrecv.exe dgsend.exe
dgrecv.exe:
 gcc dgrecv.c dgram.c -o dgrecv.exe
dgsend.exe:
 gcc dgsend.c dgram.c -o dgsend.exe
運行結果:
$./dgrecv.exe 8901&
$./dgsend.exe ComputerName 8901 "Yeah,I am on fire"
dgrecv:got a message: Yeah,I am on fire
  from:192.168.0.1:1018

總結:
伺服器:socket -> (填充結構) -> bind   -> recvfrom
用戶端:socket -> (填充結構) -> sendto

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.