C++tcp服务器和跨平台客户端

TcpServer

#define WIN32_LEAN_AND_MEAN
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <windows.h>
#include <winsock2.h>
#include <iostream>
#include <thread>
#include <mutex>
#include <chrono>
#pragma comment(lib,"ws2_32.lib")

std::mutex g_Mutex;
bool g_IsQuit = false;

void QuitServer()
{
    while (!g_IsQuit)
    {
        short key = GetAsyncKeyState('A');
        if(key&0x0001)
        {
            g_Mutex.lock();
            g_IsQuit = true;
            g_Mutex.unlock();
        }
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
    }
}

int main()
{
    //1.初始化网络环境
    WORD wVersion = MAKEWORD(2, 2);
    WSADATA wsaData;
    int err = WSAStartup(wVersion, &wsaData);

    if (err != 0)
    {
        printf("网络初始化错误,错误代码%d\n", err);
        system("pause");
        return 0;
    }

    //2.创建监听套接字
    SOCKET listenSock = socket(
        AF_INET,
        SOCK_STREAM,
        IPPROTO_TCP
    );
    if (INVALID_SOCKET == listenSock)
    {
        printf("监听套接字创建失败\n");
        WSACleanup();
        system("pause");
        return 0;
    }

    //3.设置服务器的端口信息
    sockaddr_in sin;
    sin.sin_port = htons(6666);
    sin.sin_family = AF_INET;
    sin.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//任意ip

    //4.绑定地址信息到监听套接字
    if (SOCKET_ERROR == bind(listenSock, (sockaddr*)&sin, sizeof(sin)))
    {
        printf("绑定监听套接字创建失败\n");
        closesocket(listenSock);
        WSACleanup();
        system("pause");
        return 0;
    }
    //5.开始监听
    if (SOCKET_ERROR == listen(listenSock, 100))
    {
        printf("监听出现错误\n");
        closesocket(listenSock);
        WSACleanup();
        system("pause");
        return 0;
    }

    //6.收发信息
    sockaddr_in clientaddinfo;
    int addlen = sizeof(clientaddinfo);
    SOCKET clientsock;

    clientsock = accept(listenSock, (sockaddr*)&clientaddinfo, &addlen);


    if (INVALID_SOCKET == clientsock)
    {
        printf("Accept错误\n");
        closesocket(listenSock);
        WSACleanup();
        system("pause");

        return 0;
    }

    //使用多线程转发和接收信息
    while (!g_IsQuit)
    {
        printf("接收到一个客户:%d,IP:%s,Port:&d\n",
            clientsock,
            inet_ntoa(clientaddinfo.sin_addr),
            clientaddinfo.sin_port);
        char buf[MAX_PATH] = {};
        recv(clientsock, buf, MAX_PATH - 1, 0);
        printf("接收到的数据:%s\n", buf);

        send(clientsock, "this is my backdata!", strlen("this is my backdata!") + 1,0);
    }

    //7.关闭套接字和网络环境
    closesocket(clientsock);
    closesocket(listenSock);
    WSACleanup();
    system("pause");
    return 0;
}

Linux跨平台网络客户端

#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <windows.h>
#include <winsock2.h>
#pragma comment(lib,"ws2_32.lib")
#else
#include <unistd.h>
#include <arpa/inet.h>
#include <string.h>

#define MAX_PATH    260
typedef int SOCKET;
#define INVALID_SOCKET (SOCKET)(~0)
#define SOCKET_ERROR            (-1)
#define WSACleanup() //

#endif
#include <iostream>
#include <thread>
#include <mutex>
#include <chrono>
using namespace std;

bool g_IsQuit = false;
bool g_IsSend = false;
char g_SendBuffer[MAX_PATH];
mutex g_Mutex1;
mutex g_Mutex2;

void InputData()
{
    while (!g_IsQuit )
    {
        printf("input msg:\n");
        scanf("%s",g_SendBuffer);
        if (strcmp(g_SendBuffer,"exit")==0)
        {
            g_Mutex1.lock();
            g_IsQuit = true;
            g_Mutex1.unlock();
            break;
        }else if (!g_IsSend)
        {
            g_Mutex2.lock();
            g_IsSend = true;
            g_Mutex2.unlock();
        }
        this_thread::sleep_for(chrono::milliseconds(1));
    }
}



int main()
{
    #ifdef _WIN32
    WORD wVersion = MAKEWORD(2, 2);
    WSADATA wsaData;
    int err = WSAStartup(wVersion, &wsaData);
    if (err != 0)
    {
        printf("初始化错误%d\n", err);
        system("pause");
        return 0;
    }
    #endif

    SOCKET clientSock = socket(
        AF_INET,
        SOCK_STREAM,
        IPPROTO_TCP
        );

    if (INVALID_SOCKET == clientSock)
    {
        printf("create clientsocket failed\n");
        WSACleanup();
        system("pause");
        return 0;
    }

    sockaddr_in sin;
    sin.sin_port = htons(12345);
    sin.sin_family = AF_INET;
    #ifdef _WIN32
    sin.sin_addr.S_un.S_addr = inet_addr("192.168.1.2");
    #else 
    sin.sin_addr.s_addr = inet_addr("192.168.1.2");
    #endif

    if (SOCKET_ERROR == connect(clientSock, (sockaddr*)&sin, sizeof(sin)))
    {
        printf("错误\n");
        #ifdef _WIN32
        closesocket(clientSock);
        #else
        close(clientSock);
        #endif
        WSACleanup();
        system("pause");
        return 0;
    }

    thread inputthread(InputData);
    inputthread.detach();


    char recvdata[MAX_PATH] = {};
    while (!g_IsQuit)
    {
        if (g_IsSend)
        {
            printf("start send data\n");
            send(clientSock,g_SendBuffer, strlen(g_SendBuffer) + 1, 0);
            printf("start recv data\n");
            recv(clientSock, recvdata, MAX_PATH, 0);
            printf("reved msg:%s\n", recvdata);
            g_Mutex2.lock();
            g_IsSend = false;
            g_Mutex2.unlock();
            printf("lock end\n");
        }
        this_thread::sleep_for(chrono::milliseconds(1));
    }

    #ifdef _WIN32
    closesocket(clientSock);
    #else
    close(clientSock);
    #endif
    WSACleanup();
    return 0;
}

总结

  • 跨平台注意编码
  • 通过使用内置的宏,可以进行操作系统判断 #ifdef _WIN32 #endif
  • arpa/inet.h:IP地址转换

原文链接: https://www.cnblogs.com/biu-we/p/13261114.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    C++tcp服务器和跨平台客户端

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/363671

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月2日 下午3:08
下一篇 2023年3月2日 下午3:09

相关推荐