网络编程套接字之UDP编程

1.UDP套接字编程过程

图1 UDP客户端/服务器端

sendto 与 recvfrom 函数

这两个函数的功能类似于 write 和 read 函数,可用无连接的套接字编程。其定义如下:

/* 函数功能:发送数据;
 * 返回值:若成功则返回已发送的字节数,若出错则返回-1;
 * 函数原型:
 */
#include <sys/socket.h>
#include <sys/types.h>
 
ssize_t sendto(int sockfd, void *buff, size_t nbytes, int flags,
                const struct sockaddr *destaddr, socklen_t addrlen);
 
/* 说明:
 * 该函数功能类似于write函数,除了有标识符flags和目的地址信息之外,其他参数一样;
 *
 * flags标识符取值如下:
 * (1)MSG_DONTROUTE   勿将数据路由出本地网络
 * (2)MSG_DONTWAIT    允许非阻塞操作
 * (3)MSG_EOR         如果协议支持,此为记录结束
 * (4)MSG_OOB         如果协议支持,发送带外数据
 *
 * 若sendto成功,则只是表示已将数据无错误的发送到网络,并不能保证正确到达对端;
 * 该函数通过指定目标地址允许在无连接的套接字之间发送数据(例如UDP套接字);
 */
 
 /* 函数功能:接收数据;
  * 返回值:以字节计数的消息长度,若无可用消息或对方已经按序结束则返回0,若出错则返回-1;
  * 函数原型:
  */
#include <sys/socket.h>
#include <sys/types.h>
 
ssize_t recvfrom(int sockfd, void *buff, size_t nbytes, int flags,
                struct sockaddr *addr, socklen_t *addrlen);
 /* 说明:
  * 该函数功能与read类似;
  * 若addr为非空时,它将包含数据发送者的套接字地址;
  *
  * flags标识符取值如下:
  * (1)MSG_WAITALL     等待所有数据可用
  * (2)MSG_DONTWAIT    允许非阻塞操作
  * (3)MSG_PEEK        查看已读取的数据
  * (4)MSG_OOB         如果协议支持,发送带外数据
  */

基于 UDP 套接字编程

       下面我们使用 UDP 协议实现简单的功能,客户端从标准输入读取数据并把它发送给服务器,服务器接收到数据并把该数据回射给客户端,然后客户端收到从服务器回射的数据把它显示到标准输出。其功能实现如下图所示:

UDP服务器端

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

 int main(int argc, char* argv[])
 {
     if(argc != 3){
         printf("Usage: %s [ip[ [port]\n", argv[0]);
         return 1;
     }

     int sockfd = socket(AF_INET, SOCK_DGRAM, 0); //创建socket文件描述符,SOCK_DGRAM表示UDP
     if(sockfd < 0){
         perror("socket");
         return 2;
     }

     struct sockaddr_in local; //给结构体另起一个名字
     local.sin_family = AF_INET; //地址类型
     local.sin_port = htons(atoi(argv[2])); //将端口号转换成网络字节序,16位,短整形
     local.sin_addr.s_addr = inet_addr(argv[1]);

     if(bind(sockfd,(struct sockaddr*)&local,sizeof(local)) < 0){
          perror("bind");
          return 3;
      char buf[1024];
      struct sockaddr_in client;
      while(1){
           socklen_t len = sizeof(client);
           ssize_t s = recvfrom(sockfd, buf, sizeof(buf)-1,0, (struct sockaddr*)&client, &len);
           if(s > 0){
               buf[s] = 0;
               printf("[%s,%d]: %s\n",inet_ntoa(client.sin_addr),ntohs(client.sin_port), buf);
               sendto(sockfd, buf, strlen(buf),0, (struct sockaddr*)&client, sizeof(client));
           }
       }
       return 0;
 }


                                                        
                    

客户端

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <errno.h>

int main(int argc, char* argv[])
{
        int sock = socket(AF_INET, SOCK_DGRAM, 0);
        if(sock < 0){
                perror("socket");
                return 2;
        }

        struct sockaddr_in server;
        server.sin_family = AF_INET;
        server.sin_port = htons(atoi(argv[2]));
        server.sin_addr.s_addr = inet_addr(argv[1]);

        char buf[1024];
        struct sockaddr_in peer;
        while(1){
                socklen_t len = sizeof(peer);
                printf("Please Enter#: ");
                fflush(stdout);
                ssize_t s = read(0, buf, sizeof(buf)-1);
                if(s > 0){
                        buf[s-1] = 0;
                        sendto(sock, buf, strlen(buf), 0, (struct sockaddr*)&server, sizeof(server));
                        ssize_t _s = recvfrom(sock, buf, sizeof(buf)-1, 0, (struct sockaddr*)&peer,&len);
                        if(s > 0){
                                buf[_s] = 0;
                                printf("service echo# %s\n", buf);
                        }
                }
        }
        return 0;
}





猜你喜欢

转载自blog.csdn.net/ijn842/article/details/81032937