zoukankan      html  css  js  c++  java
  • C++的socket编程学习

    前言

      不得不承认作为一个前端开发,仍有一个后台开发的梦。从socket通信开始学习,在工作之余补充学习点相关知识,记录下学习的过程。

    服务端

      服务器代码如下,在设置listen之后,通过accept获取对应的socket连接并创建线程进行通信,通信完成后关闭对应线程。

    // socket_service.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h" 
    #include <stdio.h>
    #include <Winsock2.h>
    #pragma comment(lib, "ws2_32.lib")
    
    #define LISTEN_MAX_COUNT 5
    
    DWORD WINAPI AnswerThread(LPVOID lparam)
    {
        printf("Thread ID:%4d create!
    ", GetCurrentThreadId());
        int                 ret;
        char                buf[50] = { 0 };
        char                sendBuf[80] = { 0 };
        SOCKET              clientSocket = (SOCKET)(LPVOID)lparam;
        while (true)
        {
            memset(buf, 0, sizeof(buf));
            ret = recv(clientSocket, buf, sizeof(buf), 0);
            if (ret<=0)
            {
                break;
            }
            printf("revc: %s
    ", buf);
            sprintf_s(sendBuf, "Thread ID:%4d revced", GetCurrentThreadId());
            ret = send(clientSocket, sendBuf, strlen(sendBuf) + sizeof(char), 0);
            if (ret <= 0)
            {
                break;
            }
        }
        printf("Thread ID:%4d stop!
    ", GetCurrentThreadId());
        closesocket(clientSocket);
        return 1;
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    
        WORD wVersionRequested;
        WSADATA wsaData;
        wVersionRequested = MAKEWORD(1, 1);
        if (WSAStartup(wVersionRequested, &wsaData) == INVALID_SOCKET)
        {
            return 0;
        }
    
        if (LOBYTE(wsaData.wVersion) != 1 ||
            HIBYTE(wsaData.wVersion) != 1) {
            WSACleanup();
            return 0;
        }
        SOCKET sockSrv = socket(AF_INET, SOCK_STREAM, 0);
        int len = sizeof(SOCKADDR);
        SOCKADDR_IN clientAddr;
        SOCKADDR_IN serviceAddr;
        serviceAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
        serviceAddr.sin_family = AF_INET;
        serviceAddr.sin_port = htons(27015);
        
        if (bind(sockSrv, (SOCKADDR*)&serviceAddr, len) == INVALID_SOCKET)
        {
            printf("failed bind!
    ");
            closesocket(sockSrv);
            WSACleanup();
            return 0;
        }
        if (listen(sockSrv, LISTEN_MAX_COUNT) == SOCKET_ERROR) {
            printf("Listen failed with error: %ld
    ", WSAGetLastError());
            closesocket(sockSrv);
            WSACleanup();
            return 0;
        }
    
         
        SOCKET  sockClient;
        HANDLE  hThread = NULL;
        DWORD    dwThreadId;
        while (1)
        {
            sockClient = accept(sockSrv, (SOCKADDR*)&clientAddr, &len);
            Sleep(1000);
            hThread = CreateThread(NULL, NULL, AnswerThread, (LPVOID)sockClient, 0, &dwThreadId);
            if (hThread == NULL)
            {
                printf("CreatThread AnswerThread() failed.
    ");
            }
        }
    
        closesocket(sockSrv);
        WSACleanup();
        return 0;
    }
    客户端

       客户端代码如下,在连接成功后,循环输入进行通信对话。

    // socket_client.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    #include <stdio.h>
    #include <Winsock2.h>
    
    #pragma comment( lib, "ws2_32.lib" ) 
    
    int _tmain(int argc, _TCHAR* argv[])
    {
         
        WORD wVersionRequested;
        WSADATA wsaData;
        int err;
    
        wVersionRequested = MAKEWORD(1, 1);
        if (WSAStartup(wVersionRequested, &wsaData) == INVALID_SOCKET)
        {
            return -1;
        }
    
        if (LOBYTE(wsaData.wVersion) != 1 ||
            HIBYTE(wsaData.wVersion) != 1) {
            WSACleanup();
            return -1;
        }
    
    
        SOCKET sockClient = socket(AF_INET, SOCK_STREAM, 0);
        int len = sizeof(SOCKADDR);
    
        SOCKADDR_IN local;
        local.sin_addr.S_un.S_addr = inet_addr("192.168.1.15");
        local.sin_family = AF_INET;
        local.sin_port = htons(27015);
    
        if (connect(sockClient, (SOCKADDR*)&local, len) == INVALID_SOCKET)
        {
            printf("connect error/n"); 
            return 0;
        }
    
        char inputBuf[30];
        char recvBuf[50];
        int ret;
    //    while (scanf_s("%s", inputBuf, sizeof(inputBuf)) != EOF)
        while (gets_s(inputBuf))
        {
            if (strcmp(inputBuf, "stop") ==0)
            {
                break;
            }
            ret = send(sockClient, inputBuf, strlen(inputBuf) + sizeof(char), 0);
            if (ret<=0)
            {
                printf("send failed!
    ");
                break;
            }
            ret = recv(sockClient, recvBuf, sizeof(recvBuf), 0);
            if (ret <= 0)
            {
                printf("recv failed!
    ");
                break;
            }
            printf("my reply is : %s
    ", recvBuf);
            //printf("%s
    ", inet_ntoa(local.sin_addr));
        }
    
        closesocket(sockClient);
        WSACleanup();
        return 0;
    }
    测试

      Hello World!!

    1、开启多个客户端,可以看到服务器如下输出多个线程的创建。

      

    2、客户端输入hello world!,可以得到服务器回复,并告知哪个服务器线程接收了消息。

      

    3、关闭其中一个客户端,可以看到对应线程也关闭了。

    4、关闭服务端后,可以端输入任意内容,可以看到客户端也收到提示发送失败并关闭。

  • 相关阅读:
    嵌套矩形
    Multiplication Puzzle
    animate.css在vue项目中的使用
    服务器相关知识
    webpack-cli安装和插件的安装
    新买阿里云linux服务器如何设置账号密码xshell远程登陆
    主流请求库axios库的使用
    什么是回调函数
    js------match() 方法
    cookie
  • 原文地址:https://www.cnblogs.com/stratrail/p/5226683.html
Copyright © 2011-2022 走看看