Winsock API TCP/IP网络通信

爱⌒轻易说出口 提交于 2020-03-03 07:25:02

通信流程如下:

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()\n");
        ::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()\n");
        ::WSACleanup();
        return 0;
    }
    if (::listen(s, 2) == SOCKET_ERROR)//(套接字句柄,监听队列中允许保持的尚未处理的最大连接数)
    {
        printf("Failed listen()\n");
        ::WSACleanup();
        return 0;
    }
    sockaddr_in remoteAddr;
    int nAddrLen = sizeof(remoteAddr);
    SOCKET client;
    char szText[] = "TCPServer!\r\n";
    while (TRUE)
    {
        client = ::accept(s,   //套接字句柄
                         (SOCKADDR*)&remoteAddr,//取得对方地址信息
                          &nAddrLen);//指定remoteAddr空间大小,并且返回地址实际长度
        //accept接受到来的连接,为这个连接创建新的套接字,此套接字是处理实际连接的套接字
        if (client == INVALID_SOCKET)
        {
            printf("Failed accept()\n");
            continue;
        }
        printf("接收到一个链接:%s \r\n", 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()\n");
        ::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()\n");
        ::WSACleanup();
        return 0;
    }
    char buff[256];
    int nRecv = ::recv(s, buff, 256, 0);//接收(套接字,缓冲区,长度,调用方式(通常为0))
    if (nRecv > 0)
    {
        buff[nRecv] = '\0';
        printf("接收到数据:%s", buff);
    }
    ::closesocket(s);
    ::WSACleanup();
    return 0;
}

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!