学习:WinSock TCP 短连接

TCP Socket编程概念:

服务端程序:创建socket -> bind -> listen -> accept -> recv/send -> close

客户端程序:创建socket -> connect -> recv/send -> close

流式套接字:
1、TCP/IP
2、SOCK_STREAM

网络程序 = 客户端 + 服务端

套接字 socket = IP + PORT

IP地址的转换

inet_ntoa : 功能是将网络地址转换成"."点隔的字符串格式
inet_aton : 将字符串形式的IP地址 转换 为一个32位的网络序列IP地址
inet_addr : 将字符串形式的IP地址 转换 为一个网络字节顺序的整型值

字节转换

ntohl()    // 网络字节顺序转换为主机字节顺序 long 类型
ntohs()    // 网络字节顺序转换为主机字节顺序 short 类型
htonl()    // 主机字节顺序转换为网络字节顺序 long 类型
htons()    // 主机字节顺序转换为网络字节顺序 short类型

注意:如果主机字节顺序是大端,那么转换为网络字节顺序的时候,那么转换后,仍然是大端的字节顺序。

C/S通信示例图如下:

学习:WinSock TCP 短连接_第1张图片


实现代码:

服务端:

#include
#include
#pragma comment(lib, "ws2_32.lib") //添加动态链接库

using namespace std;

int main(int argc, char * argv[]) {
    const int   BUFSIZE = 1024;
    SOCKET      ListeningSocket; //定义一个套接字变量
    SOCKET      NewConnection; //客户端的请求生成的新的套接字
    SOCKADDR_IN ClientAddr;
    SOCKADDR_IN ServerAddr;
    char        Message[BUFSIZE];
    int         ClientAddrLen;
    ZeroMemory(Message, BUFSIZE);
    
    if (argc <= 1)
    {
        cout << "USAGE: TcpServer " << endl;
        return -1;
    }

    
    int ret; //用来检查初始化成功是否
    WSADATA wsaDATA; // 创建一个WSADATA 用来初始化套接字网络库
    
    if ( (ret = WSAStartup(MAKEWORD(2,2), &wsaDATA)) != 0) { // 初始化套接字网络库WinSock2.2版本
        cout << "WSAStartup初始化失败 with error " << ret << endl;
        return -1;
    }

    //创建套接字 AF_INET协议 SOCK_STREAM流 TCP协议
    if ((ListeningSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == SOCKET_ERROR) {
        cout << "创建套接字失败 with error " << WSAGetLastError() << endl;
        WSACleanup();
        return -1; 
    }

    //绑定套接字
    ServerAddr.sin_family = AF_INET;
    ServerAddr.sin_port = htons(atoi(argv[1]));
    ServerAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);

    if (bind(ListeningSocket, (SOCKADDR *)&ServerAddr, sizeof(SOCKADDR)) == SOCKET_ERROR) {
        cout << "绑定套接字失败 with error " << WSAGetLastError() << endl;
        closesocket(ListeningSocket);
        WSACleanup();
        return -1;
    }
     
    //监听套接字
    if((ret = listen(ListeningSocket, 1)) == SOCKET_ERROR) {
        cout << "监听套接字失败 with error " << WSAGetLastError() << endl;
        closesocket(ListeningSocket);
        WSACleanup();
        return -1;
    }
    cout << "正在监听端口"<< argv[1] << "中..." << endl;


    //接收客户端数据

    ClientAddrLen = sizeof(SOCKADDR);

    if((NewConnection = accept(ListeningSocket,(SOCKADDR*)&ClientAddr, &ClientAddrLen)) == INVALID_SOCKET){//创建一个当前客户端和服务端的套接字
        cout << "创建NewConnection失败 with error " << WSAGetLastError() << endl;
        closesocket(ListeningSocket);
        WSACleanup();
        return -1;
    }

    //关闭套接字
    closesocket(ListeningSocket);

    recv(NewConnection, Message, sizeof(Message), 0);
    cout << "接收到的数据为:" << Message << endl;


    closesocket(NewConnection);
    WSACleanup();
    

    return 0;
}

客户端:

#include
#include
#pragma comment(lib, "ws2_32.lib") //添加动态链接库
#pragma warning(disable:4996) //忽略旧函数使用缺陷的警告

using namespace std;

int main(int argc, char * argv[]) {
    const int   BUFSIZE = 1024;
    SOCKET      ClientSocket;
    SOCKADDR_IN ServerAddr;
    char        SendBuf[BUFSIZE];  //发送存储的数据缓冲区
    char        BufRecv[BUFSIZE]; //接收收到的数据缓冲区
    
    ZeroMemory(SendBuf, BUFSIZE);
    ZeroMemory(BufRecv, BUFSIZE);
    strcpy(SendBuf, "Hello, My Name is Client");

    if (argc <= 2)
    {
        cout << "USAGE: TcpServer  " << endl;
        return -1;
    }

    WSADATA     WSAData;
    int         ret;
    if ((ret = WSAStartup(MAKEWORD(2, 2), &WSAData)) != 0) {
        cout << "WSAStartup初始化失败 with error " << ret << endl;
        return -1;
    }
    

    //创建套接字
    if ((ClientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == SOCKET_ERROR) {
        cout << "创建套接字失败 with error " << WSAGetLastError() << endl;
        WSACleanup();
        return -1;
    }

    //连接connet服务端
    ServerAddr.sin_family = AF_INET;
    ServerAddr.sin_addr.s_addr = inet_addr(argv[1]);
    ServerAddr.sin_port = htons(atoi(argv[2]));
    if (connect(ClientSocket, (SOCKADDR *)&ServerAddr, sizeof(ServerAddr)) == SOCKET_ERROR) {
        cout << "连接服务端失败 with error " << WSAGetLastError() << endl;
        closesocket(ClientSocket);
        WSACleanup();
        return -1;
    }

    cout << "连接建立成功!";


    //send发送数据
    if ((ret = send(ClientSocket, SendBuf, strlen(SendBuf), 0)) == SOCKET_ERROR){
        cout << "send failed with error " << WSAGetLastError() << endl;;
        closesocket(ClientSocket);
        WSACleanup();
        return -1;
    }

    //关闭套接字
    closesocket(ClientSocket);
    WSACleanup();
    return 0;
}

结果图:
学习:WinSock TCP 短连接_第2张图片

你可能感兴趣的:(学习:WinSock TCP 短连接)