阿虚
咸鱼本鱼。
咸鱼本鱼

IPV4的udp接口编程

什么是udp接口编程

和TCP一样都是系统封装好了,我们只需要调用几个函数,填几个参数就完事的事情。都是规定好且死板没套路,接口就那么几个玩不出太多的花来。

使用UDP接口的好处是什么?

  • 传输速度比TCP快
  • 不会“粘包”

使用UDP接口的坏处是什么?

  • TCP好处一个捞不着
  • 有一定概率“丢包”或数据包不完整

UDP服务端接口调用顺序

启动一个UDP服务端需要经历3个步骤。步骤是固定的死记硬背没关系没有那么多套路。

  • 1. 初始化套接字版本                                      WSAStartup
  • 2. 创建一个UDPSocket                                   socket
  • 3. 绑定IP和端口号                                         bind
  • 4. 等待其他socket发送UDP包来和答复对方 recvfrom/sendto
  • 5. 处理完请求后关闭和对方的socket链接。  closesocket

IPV4服务端例子

#define WIN32_LEAN_AND_MEAN 
#include <winsock2.h> 
#include <stdio.h>
#include <stdlib.h>

// Link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")

void tcp();
void udp();
  
int main(int argc, char **argv) 
{   
    //tcp(); 
    udp();
    return 0;
}

void udp()
{
    WSADATA wsaData;
    //0x0初始化网络库
    if (WSAStartup(
        MAKEWORD(2, 2)       //参数1表示使用的网络库版本,目前最高就是2.2
                            //虽然官方说最低只支持win vist,xp系统上还是使用2.2
        , &wsaData) != 0)   //这个参数其实并没有什么卵用。
    {
        WSACleanup();
        return -1;
    }

    //0x1 创建一个UDPSocket
    SOCKET udp_socket = socket(
        AF_INET             //参数一是使用的地址族格式?绕口,AF_INET表示使用IPV4地址
        , SOCK_DGRAM        //SOCK_DGRAM指的就是UDP协议。
        , IPPROTO_UDP);     //IPPROTO_UDP 不使用任何协议,就是纯粹的UDP流,自己做解析。
    if (udp_socket == INVALID_SOCKET)
    {
        WSACleanup();
        return -1;
    }

    //0x2 将创建的socket绑定一个IP和端口号
    struct sockaddr_in local = { 0x0 };
    local.sin_family = AF_INET;                     //指定地址族格式,需要和socket参数一一样

    local.sin_addr.s_addr = inet_addr("127.0.0.1"); //绑定的IP地址,通常指当前机器获取到的IP地址
                                                    //127.0.0.1表示本机

    local.sin_port = htons(8080);                   //端口号,目前写死8080就行了。
                                                    //后面再补充端口号这个玩意。

    //调用绑定函数真正的把socket句柄和对应的IP端口号绑定在一起。
    int ret = bind(
        udp_socket                       //把IP和端口信息和创建出来的socket句柄绑定一起
        , (struct sockaddr*)&local          //这个没啥好说的
        , sizeof(local));
    if (ret == SOCKET_ERROR)   //这个是结构体大小
    {
        WSACleanup();
        return -1;
    }
      
    while (1)
    {
        //一个端口号毕竟不是只用一次,可以多次重复监听。
        //并且一个端口号可以同时并发多个连接请求只是学习例子没必要搞那么复杂

        //0x3等待网络其他socket发来消息
        char Buffer[128] = {0x0};
        struct sockaddr_in remote = { 0x0 };
        int remote_size = sizeof(remote);
        ret = recvfrom(
            udp_socket                      //监听的socket
            , Buffer                        //接受数据bufer
            , 128                           //接受最大多大的数据
            , 0                             //
            , (struct sockaddr*)&remote
            , &remote_size);
        if (ret == SOCKET_ERROR)
        {
            Sleep(100);
            continue;
        }

        printf("接受到连接IP %s, port %d\n"
            , inet_ntoa(remote.sin_addr)  //得到请求方使用的IP地址
            , htons(remote.sin_port));    //得到请求方使用的端口号
          
        printf("recv: %s\n", Buffer);

        char SendBuffer[128] = "www.xuwu.org";
        //给对方发送一条消息报文
        ret = sendto(
            udp_socket
            , SendBuffer                    //发送数据的buf
            , sizeof(SendBuffer)            //发送了多少个字节
            , 0
            , (struct sockaddr*)&remote     //给对方发送数据
            , sizeof(remote));
        if (ret == SOCKET_ERROR)
        {
            fprintf(stderr, "send() failed: error %d\n", WSAGetLastError());
        } 
    }
}

UDP客户端接口调用顺序

启动一个tcp客户端只需要3.5个步骤。步骤是固定的死记硬背没关系没有那么多套路。

  • 0.  初始化套接字版本                                             WSAStartup
  • 1.  创建一个UDPSocket                                          socket
  • 1.5 指定连接的IP和端口号 
  • 2. 开始发送或接收对方发送来的消息或者使用        sendto/recvfrom
  • 3. 处理完请求后关闭和对方的socket链接。           closesocket

IPV4客户端例子

#define WIN32_LEAN_AND_MEAN 
#include <winsock2.h> 
#include <stdio.h>
#include <stdlib.h>

// Link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")

void tcp();
void udp();

int main(int argc, char **argv) 
{  
    //tcp();
    udp();
    return 0;
}

void udp()
{
    WSADATA wsaData;
    //0x0初始化网络库
    if (WSAStartup(
        MAKEWORD(2, 2)       //参数1表示使用的网络库版本,目前最高就是2.2
                            //虽然官方说最低只支持win vist,xp系统上还是使用2.2
        , &wsaData) != 0)   //这个参数其实并没有什么卵用。
    {
        WSACleanup();
        return -1;
    }

    //0x1 创建一个UDPSocket
    SOCKET conn_socket = socket(
        AF_INET             //参数一是使用的地址族格式?绕口,AF_INET表示使用IPV4地址
        , SOCK_DGRAM        //SOCK_DGRAM指的就是UDP协议。
        , IPPROTO_UDP);     //IPPROTO_UDP 不使用任何协议,就是纯粹的UDP流,自己做解析。
    if (conn_socket == INVALID_SOCKET)
    {
        WSACleanup();
        return -1;
    }

    //0x1.5
    struct sockaddr_in server = { 0x0 };
    server.sin_family = AF_INET;                     //指定地址族格式,需要和socket参数一一样
    server.sin_addr.s_addr = inet_addr("127.0.0.1"); //连接到目标IP地址
    server.sin_port = htons(8080);                   //连接到目标对应的端口号
    //不用填写发送的端口号?是的,发送端口号由操作系统来帮我们设置,我们并不需要填写。
    int server_size = sizeof(server);
 
    //0x2 给对方发送消息或者接受对方发过来的消息 
    char Buffer[128] = "hello world!!!";
    //发送数据给对方
    int ret = sendto(
        conn_socket
        , Buffer            //发送数据的buf
        , sizeof(Buffer)    //发送了多少个字节
        , 0
        , (struct sockaddr*)&server
        , sizeof(server));
    if (ret == SOCKET_ERROR)
    {
        //发送数据失败
        closesocket(conn_socket);
        return -1;
    }

    //接受对方发送过来的数据
    ret = recvfrom(
        conn_socket
        , Buffer            //接收buf
        , sizeof(Buffer)    //一共接收多少个字节
        , 0
        , (struct sockaddr*)&server
        , &server_size);
    if (ret == SOCKET_ERROR)
    {
        closesocket(conn_socket);
        return -1;
    }

    if (ret == 0)
    {
        closesocket(conn_socket);
        WSACleanup();
        return -1;
    }

    printf("recv:%s \n", Buffer);

    //0x3 通讯结束断开和对方的持续连接。
    closesocket(conn_socket);

    return;  
}

TCP服务端和客户端跑起来的结果

http://www.xuwu.org/wp-content/uploads/2021/06/image.png

阿虚

文章作者

发表评论

textsms
account_circle
email

咸鱼本鱼

IPV4的udp接口编程
什么是udp接口编程 和TCP一样都是系统封装好了,我们只需要调用几个函数,填几个参数就完事的事情。都是规定好且死板没套路,接口就那么几个玩不出太多的花来。 使用UDP接口的好处…
扫描二维码继续阅读
2021-06-02