windows socket通讯 master 和 slave通讯 c++

这是一个使用WindowsSocketAPI实现的TCP服务器和客户端程序。服务器监听5150端口,接受客户端连接,交换任务ID和随机数。客户端连接到服务器,发送随机数并接收任务ID,然后根据随机数睡眠相应时间。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这是一份记录

具体说明 暂无

//Master 的代码

#pragma comment(lib, "ws2_32.lib")//预编译
#include <stdio.h>
#include <winsock2.h>
#include <iostream>
#include <algorithm>

using namespace std;

int commonGetRandNumber(const int low, const int high);
typedef unsigned char uChar;

int main(int argc, char* argv[])
{
    //step1:初始化Windows Socket 2.2库
    WSADATA              wsaData;
    WSAStartup(MAKEWORD(2, 2), &wsaData);

    //step2:创建一个新的Socket来响应客户端的连接请求
    SOCKET sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

    //step3:填写服务器地址信息
    int                  port = 5150;// 端口为5150
    SOCKADDR_IN          serverAddr;
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(port);
    //serverAddr.sin_addr.s_addr =inet_addr("10.66.103.187");
    serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    //IP地址为INADDR_ANY,使用htonl将IP地址转换为网络格式

    //step4:绑定监听端口
    bind(sListen, (SOCKADDR*)&serverAddr, sizeof(serverAddr));

    //step5:开始监听,指定三次握手等待队列长度为5
    listen(sListen, 5);


    cout << "开始监听......\n" << endl;

    while (true)
    {
        //step6:接受新的连接
        SOCKET    sNewConnection;
        SOCKADDR_IN clientAddr;
        memset(&clientAddr, 0, sizeof(clientAddr));
        int clientAddrLen = sizeof(clientAddr);
        sNewConnection = accept(sListen,
            (SOCKADDR*)&clientAddr, &clientAddrLen);

        //step7:新的连接建立后,就可以互相通信了,
        //在这个简单的例子中,
        //我们发送"Welcome to Network Programing!",然后关闭连接
        //进行数据交换

        int iMenuTaskId = 1255;

        while (1)
        {
            if (iMenuTaskId >= 0xFFFFFFFF)
            {
                iMenuTaskId = 1;
            }
            else
            {
                iMenuTaskId++;
            }

            char chId1 = iMenuTaskId >> 24;
            char chId2 = iMenuTaskId >> 16;
            char chId3 = iMenuTaskId >> 8;
            char chId4 = iMenuTaskId  &  0XFF;
            


            //收
            char message[1024];
            int recvSize = recv(sNewConnection,
                message, sizeof(message), 0);
            if (recvSize <= 0)
                break;

            uChar uId1 = (unsigned char)message[0];
            uChar uId2 = (unsigned char)message[1];
            uChar uId3 = (unsigned char)message[2];
            uChar uId4 = (unsigned char)message[3];
            int iClientId = uId4 + uId3 * 0x100 + uId2 * 0x10000 + uId1 * 0x1000000;

            uChar uX1 = (unsigned char)message[4];
            uChar uX2 = (unsigned char)message[5];
            int iXNumber = uX2 + uX1 * 0x100;

            cout << "任务ID:" << iMenuTaskId << ";;;SlaveId:" << iClientId << ";;;传回来的随机X值" << iXNumber << endl;
            //printf("%s: %s\n", "hu", message);


            //发送任务ID
            char data[1024] = { 0 };
            printf("%s: ", "li");
            data[0] = chId1;
            data[1] = chId2;
            data[2] = chId3;
            data[3] = chId4;

            send(sNewConnection, data, strlen(message) + 255, 0);
        }
        //关闭与客户通讯的套接字
        closesocket(sNewConnection);
        printf("%s", "另一端关闭");
    }

    //step8:关闭套接字
    closesocket(sListen);
    //step9:释放Windows Socket DLL的相关资源
    WSACleanup();
    return 0;
}

/*
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
参数
sockfd:套接字描述符,该套接口在listen()后监听连接。
addr:(可选)指针,指向一缓冲区,其中接收为通讯层所知的连接实体的地址。Addr参数的实际格式由套接口创建时所产生的地址族确定。
addrlen:(可选)指针,输入参数,配合addr一起使用,指向存有addr地址长度的整型数。
返回值:如果没有错误产生,则accept()返回一个描述所接受包的SOCKET类型的值。
否则的话,返回INVALID_SOCKET错误,应用程序可通过调用WSAGetLastError()来获得特定的错误代码。
*/


int commonGetRandNumber(const int low, const int high)
{
    int randNum = 0;

    //生成随机数
    randNum = rand() % (high - low + 1) + low;

    return randNum;
}

// Slave的代码

/*该例程不包含错误检查代码,主要用于描述创建TCP Client SOCKET并进行通讯的流程*/
#include <stdio.h>
#include <winsock.h>
#include <iostream>

using namespace std;
#pragma comment(lib, "ws2_32.lib")//这句话的前面意思是静态加入一个lib文件也就是库文件ws2_32.lib文件,提供了对以下网络相关API的支持,若使用其中的API,则应该将ws2_32.lib加入工程(否则需要动态载入ws2_32.dll)。
int commonGetRandNumber(const int low, const int high);


typedef unsigned char uChar;

int main(int argc, char* argv[])
{
    //int First,Second;
    //step 1: 初始化Windows Socket 2.2库
    WSADATA                        wsaData;//功能是:存放windows socket初始化信息
    WSAStartup(MAKEWORD(2, 2), &wsaData);

    //step 2: 创建客户端SOCKET套接字
    SOCKET sClient = socket(AF_INET, SOCK_STREAM, 0);

    //step 3: 设置服务器地址
    sockaddr_in serverAddr;

    memset(&serverAddr, 0, sizeof(sockaddr_in));//去掉没有影响,暂时不知用途
    /*void *memset(void *s, int ch, size_t n);
    函数解释:将s中当前位置后面的n个字节 (typedef unsigned int size_t )用 ch 替换并返回 s 。
    memset:作用是在一段内存块中填充某个给定的值,它是对较大的结构体或数组进行清零操作的一种最快方法*/

    serverAddr.sin_family = AF_INET;
    //serverAddr.sin_addr.s_addr = inet_addr(argv[1]);
    //serverAddr.sin_port = htons((u_short)atoi(argv[2]));

    serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    //serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    serverAddr.sin_port = htons(5150);

    //step 4: 连接服务器
    connect(sClient, (SOCKADDR*)&serverAddr, sizeof(serverAddr));//sockaddr和sockaddr_in的区别:二者的占用的内存大小是一致的,因此可以互相转化,从这个意义上说,他们并无区别

    //step 5:与服务器进行通讯


    while (1)
    {
        char data[1024] = { 0 };
        int iRandomX = commonGetRandNumber(500, 1000);


        data[0] = sClient >> 24;
        data[1] = sClient >> 16;
        data[2] = sClient >> 8;
        data[3] = sClient & 0xFF;
        
        data[4] = iRandomX >> 8;
        data[5] = iRandomX & 0xFF;
        
        int sendSize = send(sClient, data, strlen(data) + 255, 0);//第三个参数是缓冲区中数据的长度,返回所发送的数据的总长度或SOCKET_ERROR错误


        //获取任务ID
        char getdata[1024] = { 0 };
        int recvSize = recv(sClient, getdata, 1024, 0);//第三个参数是缓冲区的长度;成功执行时,返回接收到的字节数。另一端已关闭则返回0。失败返回-1


        uChar uId1 = (unsigned char)getdata[0];
        uChar uId2 = (unsigned char)getdata[1];
        uChar uId3 = (unsigned char)getdata[2];
        uChar uId4 = (unsigned char)getdata[3];
        int iMenuTaskId = uId4 + uId3 * 0x100 + uId2 * 0x10000 + uId1 * 0x1000000;

        //获取随机数

        cout << "任务ID:"<< iMenuTaskId << ";;;;随机数和Slepp时间为:" << iRandomX << endl;
        Sleep(iRandomX);

    }

    //step 6:关闭套接字
    closesocket(sClient);

    //step 7:释放Winsock库
    WSACleanup();
    getchar();
    getchar();
    return 0;
}

/*
sockaddr_in(在netinet/in.h中定义):
struct sockaddr_in {
short int sin_family;              Address family
unsigned short int sin_port;       Port number
struct in_addr sin_addr;           Internet address
unsigned char sin_zero[8];         Same size as struct sockaddr
};
struct in_addr {
unsigned long s_addr;
};*/


int commonGetRandNumber(const int low, const int high)
{
    int randNum = 0;

    //生成随机数
    randNum = rand() % (high - low + 1) + low;

    return randNum;
}
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值