vs C++实现Socket通信、添加ws2_32.lib 动态链接库

【前言】 Windows 下的 socket 程序依赖 Winsock.dll 或 ws2_32.dll,必须提前加载。动态链接库有两种加载方式:隐式加载和显示加载。请查看:动态链接库DLL的加载  (此处是引用别人的文章)。本文是在vs下添加ws2_32.dll库。

1. 在vs下添加ws2_32.dll库

右键【项目】-【属性】-【链接器】-【输入】-【附加依赖项】,进行编辑,添加 ws2_32.dll库,去掉从父级或项目默认设置继承的勾选,如下图所示:

vs C++实现Socket通信、添加ws2_32.lib 动态链接库_第1张图片

vs C++实现Socket通信、添加ws2_32.lib 动态链接库_第2张图片

注意,下面的服务器端和客户端代码均写入了这一句——#pragma comment(lib, "ws2_32.lib") //加载 ws2_32.dll,因此两个程序都需要添加ws2_32.lib动态链接库。

2. 服务器端代码Sever.cpp

#include 
#include 
#pragma comment (lib, "ws2_32.lib")  //加载 ws2_32.dll

int main(){
    //初始化 DLL
    WSADATA wsaData;
    WSAStartup( MAKEWORD(2, 2), &wsaData);

    //创建套接字
    SOCKET servSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);

    //绑定套接字
    sockaddr_in sockAddr;
    memset(&sockAddr, 0, sizeof(sockAddr));  //每个字节都用0填充
    sockAddr.sin_family = PF_INET;  //使用IPv4地址
    sockAddr.sin_addr.s_addr = inet_addr("127.0.0.1");  //具体的IP地址
    sockAddr.sin_port = htons(1234);  //端口
    bind(servSock, (SOCKADDR*)&sockAddr, sizeof(SOCKADDR));

    //进入监听状态
    listen(servSock, 20);

    //接收客户端请求
    SOCKADDR clntAddr;
    int nSize = sizeof(SOCKADDR);
    SOCKET clntSock = accept(servSock, (SOCKADDR*)&clntAddr, &nSize);

    //向客户端发送数据
    char *str = "Hello World!";
    send(clntSock, str, strlen(str)+sizeof(char), NULL);

    //关闭套接字
    closesocket(clntSock);
    closesocket(servSock);

    //终止 DLL 的使用
    WSACleanup();

    return 0;
}

在运行服务器端代码时,有的vs会出现如下错误error C4996: 'inet_addr': Use inet_pton() or InetPton() instead or define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings,如下图:

vs C++实现Socket通信、添加ws2_32.lib 动态链接库_第3张图片

这是因为inet_addr是一个老函数,而微软就是喜欢强迫别人用它的新函数。

【解决方案】

1. 用socket的新函数代替程序出现的所有老函数,此方法学习成本太高。

2. 在项目属性里设置,告诉编译器,我就用老函数,让她不要报错了。

所以推荐使用第二种解决方案,设置方法如下:

右键【项目】-【属性】-【配置属性】-【C/C++】-【常规】-【SDL检查】的值改为“否”,如下图:

vs C++实现Socket通信、添加ws2_32.lib 动态链接库_第4张图片

再次运行,就不会报错了。

3. 客户端代码Client.cpp

#include 
#include 
#include 
#pragma comment(lib, "ws2_32.lib")  //加载 ws2_32.dll
int main(){
    //初始化DLL
    WSADATA wsaData;
    WSAStartup(MAKEWORD(2, 2), &wsaData);
    //创建套接字
    SOCKET sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
    //向服务器发起请求
    sockaddr_in sockAddr;
    memset(&sockAddr, 0, sizeof(sockAddr));  //每个字节都用0填充
    sockAddr.sin_family = PF_INET;
    sockAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    sockAddr.sin_port = htons(1234);
    connect(sock, (SOCKADDR*)&sockAddr, sizeof(SOCKADDR));
    //接收服务器传回的数据
    char szBuffer[MAXBYTE] = {0};
    recv(sock, szBuffer, MAXBYTE, NULL);
    //输出接收到的数据
    printf("Message form server: %s\n", szBuffer);
    //关闭套接字
    closesocket(sock);
    //终止使用 DLL
    WSACleanup();
    system("pause");
    return 0;
}

4. 运行调试

先运行 服务器端程序,再运行客户端程序,输出结果为:
Message form server: Hello World!

值得注意的是,由于这两个程序没有写入while循环,所以server 只接受一次 client 请求,当 server 向 client 传回数据后,程序就运行结束了。如果想再次接收到服务器的数据,必须再次运行 server,这只是一个非常简陋的 socket 程序,不能够一直接受客户端的请求。

本文的存在,只是为了讲述在vs环境下,跑通Socket程序的流程以及会遇到的问题及解决方法。

你可能感兴趣的:(vs C++实现Socket通信、添加ws2_32.lib 动态链接库)