首页 > 编程语言 >C++ - TCP/UDP网络编程

C++ - TCP/UDP网络编程

时间:2023-01-07 11:34:16浏览次数:62  
标签:recvBuf SOCKADDR UDP int sendBuf C++ TCP include wVersion

前言

socket编程分为TCP和UDP两个模块,其中TCP是可靠的、安全的,常用于发送文件等,而UDP是不可靠的、不安全的,常用作视频通话等。

如下图:

头文件与库:

#include <WinSock2.h>
​
#pragma comment(lib, "ws2_32.lib")

准备工作:

创建工程后,首先右键工程,选择属性

然后选择 C/C++ - 预处理器 - 预处理器定义

将字符串 _WINSOCK_DEPRECATED_NO_WARNINGS 添加到里面去,点击应用即可!

 

TCP

连接过程图:

 

创建tcp服务器和客户端都是按照上图的步骤来操作的!

1). 服务器

1.初始化套接字库,对应图中socket()

WORD wVersion;
WSADATA wsaData;
int err;
​
// 设置版本,可以理解为1.1
wVersion = MAKEWORD(1, 1);  // 例:MAKEWORD(a, b) --> b | a << 8 将a左移8位变成高位与b合并起来
​
// 启动
err = WSAStartup(wVersion, &wsaData);

2.创建tcp套接字,对应图中socket()

// AF_INET:ipv4   AF_INET6:ipv6
SOCKET sockSrv = socket(AF_INET, SOCK_STREAM, 0);

3.绑定到本机, 对应图中bind()

// 准备绑定信息
SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);   // 设置绑定网卡
addrSrv.sin_family = AF_INET;       // 设置绑定网络模式
addrSrv.sin_port = htons(6000);     // 设置绑定端口
// hton: host to network  x86:小端    网络传输:htons大端
​
// 绑定到本机
int retVal = bind(sockSrv, (SOCKADDR *)&addrSrv, sizeof(SOCKADDR));

4.监听,对应图中listen()

// 同时能接收10个链接,主要看参数二的设置个数
listen(sockSrv, 10);

5.接收连接请求,返回针对客户端的套接字,对应图中accept()

SOCKET sockConn = accept(sockSrv, (SOCKADDR *)&addrCli, &len);

6.发送数据,对应图中write()

sprintf_s(sendBuf, "hello client!\n");
int iSend = send(sockConn, sendBuf, strlen(sendBuf) + 1, 0);

7.接收数据,对应图中read()

recv(sockConn, recvBuf, 100, 0);

8.关闭套接字,对应图中close()

closesocket(sockConn);

9.清理套接字库

WSACleanup();

 

具体实现代码:

#include <iostream>
#include <stdio.h>
#include <WinSock2.h>
​
#pragma comment(lib, "ws2_32.lib")
​
​
int main(void) {
​
    // 1.初始化套接字库
    WORD wVersion;
    WSADATA wsaData;
    int err;
​
    // 设置版本,可以理解为1.1
    wVersion = MAKEWORD(1, 1);  // 例:MAKEWORD(a, b) --> b | a << 8 将a左移8位变成高位与b合并起来
​
    // 启动
    err = WSAStartup(wVersion, &wsaData);
    if (err != 0) {
        return err;
    }
    // 检查:网络低位不等于1 || 网络高位不等于1
    if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) {
        // 清理套接字库
        WSACleanup();
        return -1;
    }
​
    // 2.创建tcp套接字       // AF_INET:ipv4   AF_INET6:ipv6
    SOCKET sockSrv = socket(AF_INET, SOCK_STREAM, 0);
​
    // 准备绑定信息
    SOCKADDR_IN addrSrv;
    addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);   // 设置绑定网卡
    addrSrv.sin_family = AF_INET;       // 设置绑定网络模式
    addrSrv.sin_port = htons(6000);     // 设置绑定端口
    // hton: host to network  x86:小端    网络传输:htons大端
​
    // 3.绑定到本机
    int retVal = bind(sockSrv, (SOCKADDR *)&addrSrv, sizeof(SOCKADDR));
    if (retVal == SOCKET_ERROR) {
        printf("Failed bind:%d\n", WSAGetLastError());
        return -1;
    }
​
    // 4.监听,同时能接收10个链接
    if (listen(sockSrv, 10) == SOCKET_ERROR) {
        printf("Listen failed:%d", WSAGetLastError());
        return -1;
    }
​
    std::cout << "Server start at port: 6000" << std::endl;
​
    SOCKADDR_IN addrCli;
    int len = sizeof(SOCKADDR);
​
    char recvBuf[100];
    char sendBuf[100];
    while (1) {
        // 5.接收连接请求,返回针对客户端的套接字
        SOCKET sockConn = accept(sockSrv, (SOCKADDR *)&addrCli, &len);
        if (sockConn == SOCKET_ERROR) {
            //printf("Accept failed:%d", WSAGetLastError());
            std::cout << "Accept failed: " << WSAGetLastError() << std::endl;
            break;
        }
​
        //printf("Accept client IP:[%s]\n", inet_ntoa(addrCli.sin_addr));
        std::cout << "Accept client IP: " << inet_ntoa(addrCli.sin_addr) << std::endl;
​
        // 6.发送数据
        sprintf_s(sendBuf, "hello client!\n");
        int iSend = send(sockConn, sendBuf, strlen(sendBuf) + 1, 0);
        if (iSend == SOCKET_ERROR) {
            std::cout << "send failed!\n";
            break;
        }
​
        // 7.接收数据
        recv(sockConn, recvBuf, 100, 0);
        std::cout << recvBuf << std::endl;
​
        // 关闭套接字
        closesocket(sockConn);
    }
​
​
    // 8.关闭套接字
    closesocket(sockSrv);
​
    // 9.清理套接字库
    WSACleanup();
​
    return 0;
}
​

 

2). 客户端

1.初始化套接字库,对应图中socket()

WORD wVersion;
WSADATA wsaData;
int err;
​
// 可以理解为1.1
wVersion = MAKEWORD(1, 1);  // 例:MAKEWORD(a, b) --> b | a << 8 将a左移8位变成高位与b合并起来
​
// 启动
err = WSAStartup(wVersion, &wsaData);
​
// 创建TCP套接字
SOCKET sockCli = socket(AF_INET, SOCK_STREAM, 0);

2.连接服务器,对应图中connect()

// 连接服务器
int err_log = connect(sockCli, (SOCKADDR *)&addrSrv, sizeof(SOCKADDR));

3.发送数据到服务器,对应图中write()

char sendBuf[] = "你好,服务器,我是客户端!";
send(sockCli, sendBuf, strlen(sendBuf) + 1, 0);

4.接收服务器的数据,对应图中read()

char recvBuf[100];
recv(sockCli, recvBuf, sizeof(recvBuf), 0);

5.关闭套接字并清除套接字库,对应图中close()

closesocket(sockCli);
WSACleanup();

 

具体实现代码:

#include <iostream>
#include <WinSock2.h>
​
​
#pragma comment(lib, "ws2_32.lib")
​
​
int main(void) {
​
    // 1.初始化套接字库
    WORD wVersion;
    WSADATA wsaData;
    int err;
​
    // 可以理解为1.1
    wVersion = MAKEWORD(1, 1);  // 例:MAKEWORD(a, b) --> b | a << 8 将a左移8位变成高位与b合并起来
​
    // 启动
    err = WSAStartup(wVersion, &wsaData);
    if (err != 0) {
        return err;
    }
    // 检查:网络地位不等于1 || 网络高位不等于1
    if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) {
        // 清理套接字库
        WSACleanup();
        return -1;
    }
​
    // 创建TCP套接字
    SOCKET sockCli = socket(AF_INET, SOCK_STREAM, 0);
​
    SOCKADDR_IN addrSrv;
    addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");  // 服务器地址
    addrSrv.sin_port = htons(6000);     // 端口号
    addrSrv.sin_family = AF_INET;       // 地址类型(ipv4)
​
    // 2.连接服务器
    int err_log = connect(sockCli, (SOCKADDR *)&addrSrv, sizeof(SOCKADDR));
    if (err_log == 0) {
        printf("连接服务器成功!\n");
    
    } else {
        printf("连接服务器失败!\n");
        return -1;
    }
​
​
    char recvBuf[100];
    char sendBuf[] = "你好,服务器,我是客户端!";
    // 3.发送数据到服务器
    send(sockCli, sendBuf, strlen(sendBuf) + 1, 0);
​
    // 4.接收服务器的数据
    recv(sockCli, recvBuf, sizeof(recvBuf), 0);
    std::cout << recvBuf << std::endl;
​
​
    // 5.关闭套接字并清除套接字库
    closesocket(sockCli);
    WSACleanup();
​
    system("pause");
​
    return 0;
}
​

运行效果:

 

3). TCP聊天小项目

下面是根据上面的代码修改的一个聊天小项目(使用到了多线程)

只有一个服务器,服务器一直开启等待客户端连接; 客户都安可以开启多个,且可以一直连续的与服务器进行发送接收消息; 服务器给客户端发送数据,得通过1 - 9来区分到底给那个客户端发送消息,例如给第二个客户端发送消息:2你好,客户端 客户端那边接收到的数据是:你好,客户端

服务器代码:

#include <iostream>
#include <WinSock2.h>
#include <stdio.h>
#include <Windows.h>
#include <process.h>
#include <vector>
#include <conio.h>
#include <string.h>
#include <string>
​
#pragma comment(lib, "ws2_32.lib")
​
​
SOCKET sockSrv;
std::vector<SOCKET> vec_sockConn;
std::vector<SOCKADDR_IN> vec_sockaddr_in;
std::vector<int> vec_sockIndex;
​
​
// 这个结构体用作线程参数
typedef struct SERVER_CLIENT {
    SOCKET server;
    SOCKADDR_IN client;
    int clientIndex;
}SC;
​
​
​
// 判断有没有断开连接
bool IsSocketClosed(SOCKET clientSocket) {
    bool ret = false;
    HANDLE closeEvent = WSACreateEvent();
    WSAEventSelect(clientSocket, closeEvent, FD_CLOSE);
​
    DWORD dwRet = WaitForSingleObject(closeEvent, 0);
​
    if (dwRet == WSA_WAIT_EVENT_0)
        ret = true;
    else if (dwRet == WSA_WAIT_TIMEOUT)
        ret = false;
​
    WSACloseEvent(closeEvent);
    return ret;
}
​
​
// 接收请求
unsigned int WINAPI  ThreadAccept(LPVOID p) {
    static int i = 0;
    while (1) {
        SOCKADDR_IN addrCli;
        int len = sizeof(SOCKADDR);
​
        // 5.接收连接请求,返回针对客户端的套接字
        SOCKET sockConn = accept(sockSrv, (SOCKADDR *)&addrCli, &len);
        if (sockConn == SOCKET_ERROR) {
            printf("Accept failed:%d", WSAGetLastError());
        }
​
        // 存储当前服务器与客户端 连接绑定的socket
        vec_sockIndex.emplace_back(i++);
        vec_sockaddr_in.emplace_back(addrCli);
        vec_sockConn.emplace_back(sockConn);
​
        printf("\033[0;%d;40m客户端[%d]上线\033[0m\n", 31, i);
    }
    
​
    return 0;
}
​
unsigned int WINAPI  _ThreadRecv(LPVOID p) {
    char recvBuf[100];
    memset(recvBuf, 0, 100);
​
    SC _sc = *(SC *)p;
    
    while (1) {
        Sleep(20);
​
        if (IsSocketClosed(_sc.server) == true) {
            printf("客户端 [%d] 断开连接!\n", _sc.clientIndex + 1);
            break;
        }
​
​
        // 接收数据
        recv(_sc.server, recvBuf, 100, 0);
        if (strlen(recvBuf) == 0) {
            continue;
        }
    
        printf("接收到客户端 [%d] 的消息:%s\n", _sc.clientIndex + 1, recvBuf);
        memset(recvBuf, 0, 100);
    }
    return 0;
}
​
unsigned int WINAPI  ThreadRecv(LPVOID p) {
​
    static int index = 0;
​
    while (1) {
        // 还没有客户端与服务器进行连接
        if (vec_sockConn.size() == 0) {
            continue;
        }
​
        // 接收线程已经开启和客户端个数相等
        if (vec_sockConn.size()  == index) {
            continue;
        }
​
        SC sc;
        sc.server = vec_sockConn.at(index);
        sc.client = vec_sockaddr_in.at(index);
        sc.clientIndex = vec_sockIndex.at(index);
​
        HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, _ThreadRecv, (void *)&sc, 0, NULL);
​
        index++;
        Sleep(20);
    }
​
    return 0;
}
​
​
​
int main(void) {
​
    // 1.初始化套接字库
    WORD wVersion;
    WSADATA wsaData;
    int err;
​
    // 设置版本,可以理解为1.1
    wVersion = MAKEWORD(1, 1);  // 例:MAKEWORD(a, b) --> b | a << 8 将a左移8位变成高位与b合并起来
​
    // 启动
    err = WSAStartup(wVersion, &wsaData);
    if (err != 0) {
        return err;
    }
    // 检查:网络低位不等于1 || 网络高位不等于1
    if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) {
        // 清理套接字库
        WSACleanup();
        return -1;
    }
​
    // 2.创建tcp套接字       // AF_INET:ipv4   AF_INET6:ipv6
    sockSrv = socket(AF_INET, SOCK_STREAM, 0);
​
    // 准备绑定信息
    SOCKADDR_IN addrSrv;
    addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);   // 设置绑定网卡
    addrSrv.sin_family = AF_INET;       // 设置绑定网络模式
    addrSrv.sin_port = htons(6000);     // 设置绑定端口
    // hton: host to network  x86:小端    网络传输:htons大端
​
    // 3.绑定到本机
    int retVal = bind(sockSrv, (SOCKADDR *)&addrSrv, sizeof(SOCKADDR));
    if (retVal == SOCKET_ERROR) {
        printf("Failed bind:%d\n", WSAGetLastError());
        return -1;
    }
​
    // 4.监听,同时接收10个链接
    if (listen(sockSrv, 10) == SOCKET_ERROR) {
        printf("Listen failed:%d", WSAGetLastError());
        return -1;
    }
​
    std::cout << "Server start at port: 6000" << std::endl;
​
​
    // 线程句柄             // 创建线程
    HANDLE hThread_1 = (HANDLE)_beginthreadex(NULL, 0, ThreadAccept, NULL, 0, NULL);
    HANDLE hThread_2 = (HANDLE)_beginthreadex(NULL, 0, ThreadRecv, NULL, 0, NULL);
​
​
    //uiInit();
    //editPrint(0, ">");
​
​
    char sendBuf[100];
    while (1) {
​
        //printf("请输入发送内容:");
​
        char c = getchar();             // 输入发送给谁
        scanf_s("%s", sendBuf, 100);    // 输入发送的内容
​
        if (strlen(sendBuf) == 0) {
            printf("输入内容为空或者超长!\n");
        }
​
        // 1 至 9
        if (c < '1' || c > '9' || vec_sockConn.size() == 0 || c - '0' >= vec_sockConn.size() + 1) {
            while ((c = getchar()) != '\n');    // 清空输入缓冲区
            memset(sendBuf, 0, 100);
            printf("输入内容不符合规则!\n");
            continue;
        }
​
​
​
        // 发送数据
        int index = --c - '0';  // 因为下标是从零开始的,所以c要先自减
        int iSend = send(vec_sockConn.at(index) , sendBuf, strlen(sendBuf) + 1, 0);
        if (iSend == SOCKET_ERROR) {
            std::cout << "send failed!\n";
            break;
        }
​
​
        memset(sendBuf, 0, 100);
        while ((c = getchar()) != '\n');    // 清空输入缓冲区
    }
​
    // 关闭套接字
    std::vector<SOCKET>::iterator it = vec_sockConn.begin();
    for (; it != vec_sockConn.end(); it++) {
        closesocket((SOCKET)(*it));
    }
​
​
    WaitForSingleObject(hThread_1, INFINITE);
    WaitForSingleObject(hThread_2, INFINITE);
​
    CloseHandle(hThread_1);
    CloseHandle(hThread_2);
​
    // 7.关闭套接字
    closesocket(sockSrv);
​
    // 8.清理套接字库
    WSACleanup();
​
    return 0;
}
​

 

客户端代码:

#include <iostream>
#include <WinSock2.h>
#include <process.h>
#include <stdio.h>
​
#pragma comment(lib, "ws2_32.lib")
​
SOCKET sockCli;
​
​
// 判断有没有断开连接
bool IsSocketClosed(SOCKET clientSocket) {
    bool ret = false;
    HANDLE closeEvent = WSACreateEvent();
    WSAEventSelect(clientSocket, closeEvent, FD_CLOSE);
​
    DWORD dwRet = WaitForSingleObject(closeEvent, 0);
​
    if (dwRet == WSA_WAIT_EVENT_0)
        ret = true;
    else if (dwRet == WSA_WAIT_TIMEOUT)
        ret = false;
​
    WSACloseEvent(closeEvent);
    return ret;
}
​
​
unsigned int WINAPI  ThreadRecv(LPVOID p) {
    char recvBuf[100];
    memset(recvBuf, 0, 100);
​
    while (1) {
        Sleep(20);
​
        if (IsSocketClosed(sockCli) == true) {
            printf("服务器 断开连接!\n");
            break;
        }
​
        // 接收服务器的数据
        recv(sockCli, recvBuf, sizeof(recvBuf), 0);
        if (strlen(recvBuf) == 0) continue;
​
        std::cout << recvBuf << std::endl;
        memset(recvBuf, 0, 100);
    }
​
​
    return 0;
}
​
int main(void) {
​
    // 1.初始化套接字库
    WORD wVersion;
    WSADATA wsaData;
    int err;
​
    // 可以理解为1.1
    wVersion = MAKEWORD(1, 1);  // 例:MAKEWORD(a, b) --> b | a << 8 将a左移8位变成高位与b合并起来
​
    // 启动
    err = WSAStartup(wVersion, &wsaData);
    if (err != 0) {
        return err;
    }
    // 检查:网络地位不等于1 || 网络高位不等于1
    if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) {
        // 清理套接字库
        WSACleanup();
        return -1;
    }
​
    // 创建TCP套接字
    sockCli = socket(AF_INET, SOCK_STREAM, 0);
​
    SOCKADDR_IN addrSrv;
    addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");  // 服务器地址
    addrSrv.sin_port = htons(6000);     // 端口号
    addrSrv.sin_family = AF_INET;       // 地址类型(ipv4)
​
    // 连接服务器
    int err_log = connect(sockCli, (SOCKADDR *)&addrSrv, sizeof(SOCKADDR));
    if (err_log == 0) {
        printf("连接服务器成功!\n");
​
    } else {
        printf("连接服务器失败!\n");
        return -1;
    }
​
    // 线程句柄             // 创建线程
    HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, ThreadRecv, NULL, 0, NULL);
​
​
    char sendBuf[100];
    while (1) {
​
        //printf("请输入发送内容:");
        scanf_s("%s", sendBuf, 100);
​
        // 发送数据到服务器
        send(sockCli, sendBuf, strlen(sendBuf) + 1, 0);
​
        memset(sendBuf, 0, 100);
        char c;
        while ((c = getchar()) != '\n');
    }
​
​
    WaitForSingleObject(hThread, INFINITE);
    CloseHandle(hThread);
​
​
    // 关闭套接字并清除套接字库
    closesocket(sockCli);
    WSACleanup();
​
    system("pause");
​
    return 0;
}
​

 

运行效果:

 

 

UDP

UDP就比较简单了,步骤比tcp要少一些。

连接过程图:

 

 

1). 服务器

1.初始化套接字库

WORD wVersion;
WSADATA wsaData;
int err;
​
wVersion = MAKEWORD(1, 1);

2.创建套接字

SOCKET sockSrv = socket(AF_INET, SOCK_DGRAM, 0);

3.绑定

// SOCKADDR_IN addrSrv; 省略了定义和赋值
bind(sockSrv, (SOCKADDR *)&addrSrv, sizeof(SOCKADDR));

4.接收数据

char recvBuf[100];
recvfrom(sockSrv, recvBuf, 100, 0, (SOCKADDR *)&addrCli, &len);

5.发送数据

char sendBuf[] = "hello Client,I'm Server!\n";
sendto(sockSrv, sendBuf, strlen(sendBuf) + 1, 0, (SOCKADDR *)&addrCli, len);

6.关闭

closesocket(sockSrv);
WSACleanup();

 

具体实现代码:

#include <WinSock2.h>
#include <iostream>
​
#pragma comment(lib, "ws2_32.lib")
​
int main(void) {
    // 初始化套接字库
    WORD wVersion;
    WSADATA wsaData;
    int err;
​
    wVersion = MAKEWORD(1, 1);
    err = WSAStartup(wVersion, &wsaData);
    if (err != 0) {
        return err;
    }
​
    if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) {
        WSACleanup();
        return -1;
    }
​
    // 创建套接字
    SOCKET sockSrv = socket(AF_INET, SOCK_DGRAM, 0);
​
    SOCKADDR_IN addrSrv;
    addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
    addrSrv.sin_family = AF_INET;
    addrSrv.sin_port = htons(6001);
​
    // 绑定到本机6001端口
    bind(sockSrv, (SOCKADDR *)&addrSrv, sizeof(SOCKADDR));
​
    // 接收请求,处理请求
    SOCKADDR_IN addrCli;
    int len = sizeof(SOCKADDR);
​
    char sendBuf[] = "hello Client,I'm Server!\n";
    char recvBuf[100];
​
    std::cout << "start UDP server with port 6001" << std::endl;
    while (1) {
        // 接收数据
        recvfrom(sockSrv, recvBuf, 100, 0, (SOCKADDR *)&addrCli, &len);
        std::cout << "Recv:" << recvBuf << std::endl;
​
        // 发送数据
        sendto(sockSrv, sendBuf, strlen(sendBuf) + 1, 0, (SOCKADDR *)&addrCli, len);
        std::cout << "Send:" << sendBuf << std::endl;
    }
​    // 关闭
    closesocket(sockSrv);
    WSACleanup();
​
    return 0;
}
​

 

2). 客户端

1.初始化套接字库

WORD wVersion;
WSADATA wsaData;
int err;
​
wVersion = MAKEWORD(1, 1);

2.创建UDP套接字

SOCKET sockCli = socket(AF_INET, SOCK_DGRAM, 0);
SOCKADDR_IN addrSrv;

3.接收数据

char recvBuf[100];
recvfrom(sockCli, recvBuf, 100, 0, (SOCKADDR *)&addrCli, &len);

4.发送数据

char sendBuf[] = "hello Client,I'm Server!\n";
sendto(sockCli, sendBuf, strlen(sendBuf) + 1, 0, (SOCKADDR *)&addrSrv, len);

5.关闭

closesocket(sockSrv);
WSACleanup();

 

具体实现代码:

#include <WinSock2.h>
#include <iostream>
​
#pragma comment(lib, "ws2_32.lib")
​
​
int main(void) {
​
    // 初始化套接字库
    WORD wVersion;
    WSADATA wsaData;
    int err;
​
    wVersion = MAKEWORD(1, 1);
    err = WSAStartup(wVersion, &wsaData);
    if (err != 0) {
        return err;
    }
​
    if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) {
        WSACleanup();
        return -1;
    }
​
    // 创建UDP套接字
    SOCKET sockCli = socket(AF_INET, SOCK_DGRAM, 0);
    SOCKADDR_IN addrSrv;
    addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
    addrSrv.sin_family = AF_INET;
    addrSrv.sin_port = htons(6001);
​
    SOCKADDR_IN addrCli;
    int len = sizeof(SOCKADDR);
​
    char sendBuf[] = "hello, I'm Client!\n";
    char recvBuf[100];
​    // 发送数据
    std::cout << "send to Server: " << sendBuf << std::endl;
    sendto(sockCli, sendBuf, strlen(sendBuf) + 1, 0, (SOCKADDR *)&addrSrv, len);
​    
    // 接收数据
    recvfrom(sockCli, recvBuf, 100, 0, (SOCKADDR *)&addrCli, &len);
    std::cout << "recv from: " << recvBuf << std::endl;
​
​    // 关闭
    closesocket(sockCli);
    WSACleanup();
​
    system("pause");
    return 0;
}
​

 

运行效果:

 

总结

socket的具体细节用法我不太清楚,现阶段也只是熟悉TCP的一些简单操作,UDP的话也还不是太懂,不懂的是不知道在具体项目中该如何进行使用它们。 那个TCP的小项目也只是自己琢磨搞出来的,不知掉具体项目会不会这样去写!

 

————————————————

版权声明:本文为CSDN博主「cpp_learners」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/cpp_learner/article/details/121798854

标签:recvBuf,SOCKADDR,UDP,int,sendBuf,C++,TCP,include,wVersion
From: https://www.cnblogs.com/zhuchunlin/p/17032316.html

相关文章

  • LLVM IR与C++ MUL函数代码
    LLVMIR与C++MUL函数代码使用LLVMIR写程序熟悉LLVMIR最好的办法就是使用IR写几个程序。在开始写之前,建议先花30分钟-1个小时再粗略阅读下官方手册(https://llvm.org/do......
  • C/C++学生信息管理系统[2023-01-06]
    C/C++学生信息管理系统[2023-01-06]题目6学生信息管理系统(任选)本系统要求设计一个学生信息管理系统,能够进行学生信息的录入、查找,要求考虑查找效率。本题目要求采用......
  • c++ 指针与引用
    引用很易与指针混淆,它们之间有三个主要的不同:不存在空引用。引用必须连接到一块合法的内存。一旦引用被初始化为一个对象,就不能被指向到另一个对象。指针可以在任何时候......
  • 数独游戏c++
    问题I:数独游戏时间限制:1.000Sec内存限制:128MB题目描述给你一个N×N的表格(3<N<10),在表格中事先已经填入了一部分的数字,现在请你的表格中空余的格子里填入1~N范围......
  • Dijkstra(迪杰斯特拉)算法C++实现&讲解
    Dijkstra迪杰斯特拉算法及C++实现Dijkstra算法是典型的最短路径路由算法,用来计算一个节点到其他所有节点的最短路径。算法的基本思想和流程是:1.初始化出发点到其它各点的......
  • java基础:UDP通信
    原文:Java实现UDP通信-简书(jianshu.com)UDP(UserDatagramProtocol),即用户数据报协议,UDP只提供数据的不可靠传递,它一旦把应用程序发给网络层的数据发送出去,就不保留数据......
  • C++ 不知树系列之二叉堆排序(递归和非递归实现上沉、下沉算法)
    1.前言什么是二叉堆?二叉堆是有序的完全二叉树,在完全二叉树的基础上,二叉堆提供了有序性特征:二叉堆的根结点上的值是整个堆中的最小值或最大值。当根结点上的值......
  • bzip2 C/C++ 库bzlib.h使用案例:读取.bz2文件
    准备从网上下载bzip2库,我下载的是V1.0.8版本的。然后在C工程中添加一个筛选器(文件夹)名叫bzlib,然后把下载的库中的如下9个文件,添加到其中:代码主函数代码如下:#include......
  • C++可执行文件绝对路径获取与屏蔽VS安全检查
    :前言前几天写新项目需要用到程序所在绝对路径的时候,发现网上居然一点相关分享都没有。:_pgmptr翻箱倒柜找出了几本教程,发现了一个叫_pgmptr的东西。进去看了一下,在s......
  • C++ 文件读入速度测试
    在信息学竞赛中,输入数据规模可能会很大,这时候就需要注意文件读取的效率。本文在Linux环境下测试了C++几种常见读入方式的效率。1.系统环境ArchLinuxx86_64默认L......