• Winsock API TCP/IP网络通信


    通信流程如下:

    1、Winsock库的装入、初始化

           #pragma comment(lib,"WS2_32.lib")、WSAStartup()

    2、套接字的创建(服务器端是监听套接字)

          socket()

    3、绑定套接字到指定的IP地址和端口

         bind()

    4、设置套接字进入监听状态(服务器端)+接受连接请求(服务器端)

        listen()、accept()

    5、请求与服务器连接

       connect()

    6、收发数据

        send()、recv()

    7、关闭套接字,释放Winsock库

          closesocket()、WSACleanup()

    详细流程如下:

    服务器端代码:

    // TCPServer.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    #include <WinSock2.h>
    #include <stdio.h>
     
    #pragma comment(lib,"WS2_32.lib") //包含相应库文件
    
    int main()
    {
        WSADATA wsaData;//结构体。(DLL库)建议版本/支持的最高版本/描述字符串/系统状态字符串/同时支持最大套接字数量
        WORD sockVersion = MAKEWORD(2, 0);//windows socket api 版本
        ::WSAStartup(sockVersion, &wsaData);  //必须首先执行。其指定了API版本,取得DLL库的详细信息
        //int a=::WSAGetLastError();//WSAStartup函数执行成功返回0,否则使用WSAGetLastError查看出错信息
        SOCKET s = ::socket(AF_INET, //套接字使用的地址格式,winSock中只能是AF_INET
                            SOCK_STREAM, //指定套接字类型(SOCK_DGRAM/RAW(数据报/原始))
                            IPPROTO_TCP);//使用协议类型,前一个是SOCK_STREAM/SOCK_DGRAM时可以为0。
        if (s == INVALID_SOCKET)
        {
            printf("Failed socket()
    ");
            ::WSACleanup();//对应WSAStartup
            return 0;
        }
        sockaddr_in sin;
        sin.sin_family = AF_INET; //地址家族(只能是AF_INET)
        sin.sin_port = htons(8888); //端口地址(网络字节顺序)为0时自动分配(1024~5000)
        sin.sin_addr.S_un.S_addr = INADDR_ANY;//IP地址。为INADDR_ANY自动取得本机所有IP
    
        if (::bind(s, (LPSOCKADDR)&sin, sizeof(sin)) == SOCKET_ERROR)//(套接字句柄,本地地址,地址长度)
        {
            printf("Failed bind()
    ");
            ::WSACleanup();
            return 0;
        }
        if (::listen(s, 2) == SOCKET_ERROR)//(套接字句柄,监听队列中允许保持的尚未处理的最大连接数)
        {
            printf("Failed listen()
    ");
            ::WSACleanup();
            return 0;
        }
        sockaddr_in remoteAddr;
        int nAddrLen = sizeof(remoteAddr);
        SOCKET client;
        char szText[] = "TCPServer!
    ";
        while (TRUE)
        {
            client = ::accept(s,   //套接字句柄
                             (SOCKADDR*)&remoteAddr,//取得对方地址信息
                              &nAddrLen);//指定remoteAddr空间大小,并且返回地址实际长度
            //accept接受到来的连接,为这个连接创建新的套接字,此套接字是处理实际连接的套接字
            if (client == INVALID_SOCKET)
            {
                printf("Failed accept()
    ");
                continue;
            }
            printf("接收到一个链接:%s 
    ", inet_ntoa(remoteAddr.sin_addr));//inet_ntoa
            ::send(client, szText, strlen(szText), 0);//发送数据(套接字,数据,数据长度,调用方式(通常为0))
            ::closesocket(client);//关闭
        }
        ::closesocket(s);//关闭
        ::WSACleanup();//clean
        return 0;
    }

    客户机代码:

    // TCPClient.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    #include<WinSock2.h>
    #include<stdio.h>
    
    #pragma comment(lib,"WS2_32.lib")
    
    int main()
    {
        WSADATA wsaData;
        WORD sockVerion = MAKEWORD(2, 0);
        ::WSAStartup(sockVerion, &wsaData);
    
        SOCKET s = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if (s == INVALID_SOCKET)
        {
            printf("Failed socket()
    ");
            ::WSACleanup();
            return 0;
        }
    
        sockaddr_in servAddr; //远程地址信息
        servAddr.sin_family = AF_INET;
        servAddr.sin_port = htons(8888);
        servAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");//没有联网可以直接写127.0.0.1
        if (::connect(s,       //套接字
                     (sockaddr*)&servAddr,  //远程地址信息
                     sizeof(servAddr)) == -1)//地址长度
        {
            printf("Failed connect()
    ");
            ::WSACleanup();
            return 0;
        }
        char buff[256];
        int nRecv = ::recv(s, buff, 256, 0);//接收(套接字,缓冲区,长度,调用方式(通常为0))
        if (nRecv > 0)
        {
            buff[nRecv] = '';
            printf("接收到数据:%s", buff);
        }
        ::closesocket(s);
        ::WSACleanup();
        return 0;
    }
  • 相关阅读:
    QQ邮箱接收Gmail邮件的方法
    Python连接Mysql数据库——pymysql驱动
    nodejs pm2守护进程使用
    出现次数超过一半的数
    Good Hacker——模拟&&双向队列
    poj 2481 Cows——树状数组&&python
    Navicat15破解注册机详细教程-Navicat Keygen Patch v5.6.0
    宝塔面板6.X在Docker中安装宝塔面板5.9.1 – 我是不是太闲了?
    Vue全家桶(Vue-cli、Vue-route、vuex)
    基于.net core微服务(Consul、Ocelot、Docker、App.Metrics+InfluxDB+Grafana、Exceptionless、数据一致性、Jenkins)
  • 原文地址:https://www.cnblogs.com/cteng-common/p/WinsockCommunicate.html
Copyright © 2020-2023  润新知