《UDP用到的大多数函数在上一片TCP中已讲解,这儿就不再重复了,只有接受和发送所用的函数不同》

  1. 函数

(1)接受——recvfrom()

套接字编程——基于UDP协议_socket

(2)发送——sendto()

套接字编程——基于UDP协议_udp_02

a. 参数

sockfd: 表示一个已经建立的socket编号(描述符);

buf: 接受数据的缓冲区;

len: 缓冲区的大小;

flags: 调用操作方式,当设为0时,表示用阻塞方式接收;

src_addr: 发送方网络地址信息,指向装有发送方地址的缓存区;  

addrlen: 指向src_addr缓存区长度值;

b. 返回值

   成功返回读入/发送的字节数,失败返回-1。


2. 程序实现图

(1). 服务器的工作流程:首先调用socket函数创建一个Socket,然后调用bind函数将其与本机地址以及一个本地端口号绑定,接收到一个客户端时,服务器显示该客户端的IP地址,并将字串返回给客户端。

(2). 客户端的工作流程:首先调用socket函数创建一个Socket,填写服务器地址及端口号,从标准输入设备中取得字符串,将字符串传送给服务器端,并接收服务器端返回的字符串。最后关闭该socket。  

套接字编程——基于UDP协议_socket_03

3. 程序实现

//udp_server.c
  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<string.h>
  4 #include<netinet/in.h>
  5 #include<sys/types.h>
  6 #include<sys/socket.h>
  7 
  8 void usage(const char* argv)
  9 {   
 10     printf("%s [ip] [port]\n",argv);
 11     exit(0);
 12 }
 13 static int startup(int ip,int port)
 14 {   
 15     //创建套接字
 16     int sock=socket(AF_INET,SOCK_DGRAM,0);
 17     if(sock<0)
 18     {
 19         perror("socket");
 20         exit(1);
 21     }
 22     //设置socket
 23     struct sockaddr_in local;
 24     local.sin_family=AF_INET;
 25     local.sin_port=htons(port);
 26     local.sin_addr.s_addr=inet_addr(ip);
 27     //绑定
 28     if(bind(sock,(struct sockaddr*)&local,sizeof(local))<0)
 29     {
 30         perror("bind");
 31         exit(2);
 32     }
 33     return sock;
 34 }
 35 int main(int argc,char* argv[])
 36 {
 37     if(argc!=3)
 38     {
 39         usage(argv[0]);
 40         exit(3);
 41     }
 42     int r_ip=argv[1];
 43     int r_port=atoi(argv[2]);
 44 
 45     int server_sock=startup(r_ip,r_port);
 46     if(server_sock<0)
 47     {
 48         perror("startup");
 49         exit(4);
 50     }
 51 
 52     char buf[1024];
 53     struct sockaddr_in client;
 54     socklen_t len =sizeof(client);
 55     while(1)
 56     {
 57         memset(buf,'\0',sizeof(buf));
 58         ssize_t size = recvfrom(server_sock,buf,sizeof(buf)-1,0,\
                               (struct sock addr*)&client,&len);
 59         if(size<0)
 60         {
 61             perror("recvform");
 62             exit(1);
 63         }
 64         printf("client [%s] [%d]# %s\n",inet_ntoa(client.sin_addr),\
                               ntohs(client.sin_port),buf);
 65     }
 66     return 0;
 67 }
 
 //udp_client.c
  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<string.h>
  4 #include<netinet/in.h>
  5 #include<sys/types.h>
  6 #include<sys/socket.h>
  7 void usage(const char* argv)
  8 {   
  9     printf("%s [ip] [port]\n",argv);
 10     return ;
 11 }
 12 int main(int argc,char* argv[])
 13 {
 14     if(argc!=3)
 15     {
 16         usage(argv[0]);
 17         exit(1);
 18 
 19     }
 20 
 21     char* r_ip=argv[1];
 22     int r_port=atoi(argv[2]);
 23 
 24     int sock=socket(AF_INET,SOCK_DGRAM,0);
 25     if(sock<0)
 26     {
 27         perror("socket");
 28         exit(2);
 29     }
 30 
 31     struct sockaddr_in remote;
 32     remote.sin_family=AF_INET;
 33     remote.sin_port=htons(r_port);
 34     remote.sin_addr.s_addr=inet_addr(r_ip);
 35 
 36     char buf[1024];
 37     while(1)
 38     {
 39         memset(buf,'\0',sizeof(buf));
 40         printf("client: ");
 41         fflush(stdout);
 42         gets(buf);
 43         ssize_t _s=sendto(sock,buf,sizeof(buf),0,\
                           (struct sockaddr*)&remote,sizeof(remote));
 44         if(_s<0)
 45         {
 46             perror("sendto");
 47             exit(3);
 48         }
 49     }
 50     return 0;
 51 }
 
 //start.sh
  1 #!/bin/bash
  2 
  3 ./udp_server 192.168.163.128 8080
  
 //makefile
  1 .PHONY:all
  2 all:udp_client udp_server
  3 udp_client:udp_client.c
  4     gcc -o $@ $^
  5 udp_server:udp_server.c
  6     gcc -o $@ $^ 
  7 .PHONY:clean
  8 clean:
  9     rm -f udp_client udp_server

输出结果:

udp_server.c:

套接字编程——基于UDP协议_socket_04

udp_client.c:

套接字编程——基于UDP协议_udp_05