windows 下最小化 tcp/udp 实例

实际 windows 下 socket 编程和 linux 下几乎没有什么区别,函数名、结构体信息等都一模一样的,因为这些并非是操作系统所设计决定的。而是由公共的组织在维护和约定这些规范。在 windows 下唯一与 linux 不同的就是需要自己手动加载套接字库。其他几乎完全一致,参考以下代码。


TCP 程序服务端/客户端代码

#include <Winsock2.h>
#include <iostream>

using namespace std;

#pragma comment(lib,"Ws2_32.lib")

int main(int argc, char* argv[])
{
    WSADATA wsaData;
    WORD wVersion = MAKEWORD(2, 2);
    // 加载socket库
    int wsaResult = WSAStartup(wVersion, &wsaData);
    if (wsaResult != 0)
    {
        return -1;
    }
    // 判断加载的库是否是正确的版本
    if (LOBYTE(wsaData.wVersion) != 2 ||
        HIBYTE(wsaData.wVersion) != 2)
    {
        WSACleanup();
        return -2;
    }
    // 创建 socket 连接
    SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);

    sockaddr_in srvaddr;
    srvaddr.sin_family = AF_INET;
    srvaddr.sin_addr.S_un.S_addr = htonl(ADDR_ANY);
    srvaddr.sin_port = htons(8000);
    // 绑定服务器的IP和端口
    bind(sock, (sockaddr*)&srvaddr, sizeof(srvaddr));
    // 监听
    listen(sock, 20);

    sockaddr_in cntaddr;
    int len = sizeof(cntaddr);
    char recvBuf[512];
    while (1)
    {
        // 等待客户端连接
        SOCKET conn = accept(sock, (sockaddr*)&cntaddr, &len);
        // 有链接后接收数据
        int ret = recv(conn, recvBuf, sizeof(recvBuf), 0);
        cout << "recv data : " << ret << recvBuf << endl;
    }

    // 关闭 socket 
    closesocket(sock);
    WSACleanup();
    return 0;
}

客户端代码

#include <WinSock2.h>
#include <Ws2tcpip.h>
#include <iostream>

using namespace std;

#pragma comment(lib,"Ws2_32.lib")

int main(int argc, char* argv[])
{
    // 加载套接字库
    WSADATA wsaData;
    WORD wVersion = MAKEWORD(2, 2);
    int wsaResult = WSAStartup(wVersion, &wsaData);
    if (wsaResult != 0)
    {
        return -1;
    }

    // 判断加载的库版本是否正确
    if (LOBYTE(wsaData.wVersion) != 2 ||
        HIBYTE(wsaData.wVersion) != 2)
    {
        WSACleanup();
        return -2;
    }

    // 创建 socket 
    SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);

    // 构建服务端信息并连接
    sockaddr_in srvaddr;
    srvaddr.sin_family = AF_INET;
    inet_pton(AF_INET, "127.0.0.1", &(srvaddr.sin_addr));
    srvaddr.sin_port = htons(8000);
    connect(sock, (sockaddr*)&srvaddr, sizeof(srvaddr));

    // 向服务端发送数据
    char sendBuf[] = "Windows Socket 通信测试程序";
    send(sock, sendBuf, sizeof(sendBuf), 0);

    // 关闭套接字
    closesocket(sock);
    // 销毁套接字库
    WSACleanup();
    return 0;
}

创建 win32 控制台应用程序的空项目,将以上代码复制到你的 cpp 中就可以直接编译运行了,代码中客户端会连接服务端发送一句 “Windows Socket 通信测试程序”。

UDP 程序服务端/客户端代码

#include <WinSock2.h>
#include <Ws2tcpip.h>
#include <iostream>

using namespace std;

#pragma comment(lib,"Ws2_32.lib")

int main(int argc, char* argv[])
{
    // 加载套接字库
    WORD wVersion = MAKEWORD(2, 2);
    WSAData wsData;
    WSAStartup(wVersion, &wsData);

    // 创建套接字
    SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0);

    // 绑定本地IP和端口
    sockaddr_in srvaddr;
    srvaddr.sin_family = AF_INET;
    srvaddr.sin_addr.S_un.S_addr = htonl(ADDR_ANY);
    srvaddr.sin_port = htons(8000);
    bind(sock, (sockaddr*)&srvaddr, sizeof(srvaddr));

    // 预分配各种内存,然后循环接收客户端数据
    sockaddr_in cntaddr;
    int len = sizeof(cntaddr);
    char recvBuf[1024];
    char szAddress[16];
    while (1)
    {
        // 接收数据并把客户端信息存放到 cntaddr 结构体中
        recvfrom(sock, recvBuf, sizeof(recvBuf), 0, (sockaddr*)&cntaddr, &len);
        // 将结构体中的IP信息转换存放到char数组中
        inet_ntop(AF_INET, &(cntaddr.sin_addr.S_un.S_addr), szAddress, sizeof(szAddress));
        // 打印客户端ip和发送过来的消息
        cout << szAddress << " : " << recvBuf << endl;
    }

    // 关闭套接字
    closesocket(sock);
    // 卸载套接字库
    WSACleanup();
    return 0;
}

客户端代码

#include <WinSock2.h>
#include <Ws2tcpip.h>
#include <iostream>

using namespace std;

#pragma comment(lib,"Ws2_32.lib")

int main(int argc, char* argv[])
{
    // 加载套接字库
    WORD wVersion = MAKEWORD(2, 2);
    WSAData wsData;
    WSAStartup(wVersion, &wsData);

    // 创建套接字
    SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0);

    // 构建服务器信息直接向服务器发送数据,不像TCP无需connect
    sockaddr_in srvaddr;
    srvaddr.sin_family = AF_INET;
    inet_pton(AF_INET, "127.0.0.1", &(srvaddr.sin_addr.S_un.S_addr));
    srvaddr.sin_port = htons(8000);
    char sendBuf[] = "hello server";
    sendto(sock, sendBuf, sizeof(sendBuf), 0, (sockaddr*)&srvaddr, sizeof(srvaddr));

    // 关闭套接字
    closesocket(sock);
    // 卸载套接字库
    WSACleanup();
    return 0;
}

同样适用 win32 控制台应用程序空项目编译即可运行。

 

发表评论