Windows C语言 UDP通信demo

目录

  • 编译环境
  • 快速入门
    • 编译指令
  • 服务端code
  • 客户端code
  • 参考文章以及遇到的问题

编译环境

我的demo是通过此文章从C++更改成的C,编译环境使用的是Mingw,如下图所示
Windows C语言 UDP通信demo_第1张图片

快速入门

  1. 拷贝代码
  2. 编译
  3. 互传消息

编译指令

  1. 客户端:gcc .\udpclient.c -lwsock32 -o udpclient.exe
  2. 服务端:gcc .\udpserver.c -lwsock32 -o udpserver.exe

Windows C语言 UDP通信demo_第2张图片
运行两个可执行程序
在这里插入图片描述
客户端给目标地址(127.0.0.1(本机地址)),端口为4567发送数据数据nihao
在这里插入图片描述
本机服务端接收到客户端发送的数据,准备给客户端返回数据nihaoya
在这里插入图片描述
这时候已经代表了一次通讯的结束,代码中还有对bye的判断,其实是多余的,如下图所示,这时候服务端接收到了bye,退出了程序,但是客户端没退出,需要强制退出,所以我认为这个bye是多余的。
Windows C语言 UDP通信demo_第3张图片

服务端code

udpserver.c

#include <winsock2.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>

#pragma comment(lib, "ws2_32.lib")
#define BUFFER_SIZE 1024

#define SERVER_FAMILY AF_INET
#define SERVER_PORT 4567
#define SERVER_ADDR INADDR_ANY

void config_server(SOCKADDR_IN *addr_server)
{
    addr_server->sin_family = SERVER_FAMILY;
    addr_server->sin_port = htons(SERVER_PORT);
    addr_server->sin_addr.S_un.S_addr = SERVER_ADDR;
}

int main()
{
    WSADATA WSAData;
    char receBuf[BUFFER_SIZE];
    char Response[BUFFER_SIZE];
    if (WSAStartup(MAKEWORD(2, 2), &WSAData) != 0)
    {
        printf("init error\n");
        exit(1);
    }
    SOCKET sockServer = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (sockServer == INVALID_SOCKET)
    {
        printf("Failed socket() \n");
        return 0;
    }
    SOCKADDR_IN addr_Server; // 服务器的地址等信息
    config_server(&addr_Server);

    if (bind(sockServer, (SOCKADDR *)&addr_Server, sizeof(addr_Server)) == SOCKET_ERROR)
    { // 服务器与本地地址绑定
        printf("Failed socket() %d \n", WSAGetLastError());
        return 0;
    }

    SOCKADDR_IN addr_Clt;
    int fromlen = sizeof(addr_Clt);

    while (true)
    {
        int last = recvfrom(sockServer, receBuf, sizeof(receBuf), 0, (SOCKADDR *)&addr_Clt, &fromlen);
        printf("last:%d\n", last);
        if (last > 0)
        {                         // 判断接收到的数据是否为空
            receBuf[last] = '\0'; // 给字符数组加一个'\0',表示结束了。不然输出有乱码
            if (strcmp(receBuf, "bye") == 0)
            {
                printf("client disconnect...\n");
                closesocket(sockServer);
                return 0;
            }
            else
            {
                printf("receive data(%s):%s\n", inet_ntoa(addr_Clt.sin_addr), receBuf);
            }
        }
        printf("please input send data:");
        scanf("%s", Response);
        printf("Response:%s,len:%d\n", Response, strlen(Response));
        int r_sento = sendto(sockServer, Response, strlen(Response), 0, (SOCKADDR *)&addr_Clt, sizeof(SOCKADDR));
        printf("return :%d\n", r_sento);
    }

    closesocket(sockServer);

    WSACleanup();
    return 0;
}

客户端code

udpclient.c

#include <winsock2.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>

#pragma comment(lib, "ws2_32.lib")
#define BUFFER_SIZE 1024 // 缓冲区大小

#define SERVER_FAMILY AF_INET
#define SERVER_PORT 4567
#define SERVER_ADDR "127.0.0.1"

static char s_receBuf[BUFFER_SIZE]; // 发送数据的缓冲区
static char s_sendBuf[BUFFER_SIZE]; // 接受数据的缓冲区

void config_server(SOCKADDR_IN *addr_server)
{
    addr_server->sin_family = SERVER_FAMILY;
    addr_server->sin_port = htons(SERVER_PORT);
    addr_server->sin_addr.S_un.S_addr = inet_addr(SERVER_ADDR);
}

int main()
{
    SOCKET sock_Client; // 客户端用于通信的Socket
    WSADATA WSAData;

    if (WSAStartup(MAKEWORD(2, 2), &WSAData) != 0)
    {
        printf("init error");
        return -1;
    } // 初始化

    sock_Client = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); // 创建客户端用于通信的Socket

    SOCKADDR_IN addr_server; // 服务器的地址数据结构
    config_server(&addr_server);

    SOCKADDR_IN sock;
    int len = sizeof(sock);
    while (true)
    {
        printf("please input send data:");
        scanf("%s", s_sendBuf);
        sendto(sock_Client, s_sendBuf, strlen(s_sendBuf), 0, (SOCKADDR *)&addr_server, sizeof(SOCKADDR));
        // int last = recv(sock_Client, s_receBuf, strlen(s_receBuf), 0); // (调用recv和recvfrom都可以)
        int last = recvfrom(sock_Client, s_receBuf, sizeof(s_receBuf), 0, (SOCKADDR *)&sock, &len);
        printf("last:%d,%s\n", last, s_receBuf);
        if (last > 0)
        {
            s_receBuf[last] = '\0'; // 给字符数组加一个'\0',表示结束了。不然输出有乱码
            if (strcmp(s_receBuf, "bye") == 0)
            {
                printf("server disconnect\n");
                break;
            }
            else
            {
                printf("receive data:%s\n", s_receBuf);
            }
        }
    }

    closesocket(sock_Client);
    WSACleanup();

    return 0;
}

参考文章以及遇到的问题

参考文章:
C语言实现Windows下获取IP和MAC地址
Windows网络编程之UDP通信

其中Windows网络编程之UDP通信文章中客户端以及服务端都有bug,会造成通信失败,或者程序崩溃的情况。
服务端bug如下图所示
Windows C语言 UDP通信demo_第4张图片
Windows C语言 UDP通信demo_第5张图片
客户端bug如下图所示
Windows C语言 UDP通信demo_第6张图片

你可能感兴趣的:(嵌入式,udp,c语言,网络)