C/C++动态库创建及使用,tcpip客户端测试

本文介绍了如何在VisualStudio中创建一个动态链接库(DLL),封装一个TCP客户端。通过使用externC和_declspec关键字来确保函数接口在C++中可用,并且可以在其他项目中导入。主要步骤包括定义函数接口,使用dllexport导出函数,然后在外部应用程序中使用dllimport导入这些函数,以便于通信。示例代码展示了TCP客户端的初始化、发送、接收和关闭功能。
摘要由CSDN通过智能技术生成

学习记录
学习一下创建动态链接库,封装一个Socket客户端dll

1. vs新建文件

2. pch.h文件,申明函数接口

extern “C”:是C++特有的指令(C无法使用该指令),目的在于支持C++与C混合编程。作用是告诉C++编译器用C规则编译指定的代码(除函数重载外,extern “C”不影响C++其他特性)。
dllexport是在这些类、函数以及数据的申明的时候使用。用他表明这些东西可以被外部函数使用,即(dllexport)是把 DLL中的相关代码(类,函数,数据)暴露出来为其他应用程序使用。使用了(dllexport)关键字,相当于声明了紧接在(dllexport)关键字后面的相关内容是可以为其他程序使用的。
dllimport是在外部程序需要使用DLL内相关内容时使用的关键字。当一个外部程序要使用DLL 内部代码(类,函数,全局变量)时,只需要在程序内部使用(dllimport)关键字声明需要使用的代码就可以了,即(dllimport)关键字是在外部程序需要使用DLL内部相关内容的时候才使用。(dllimport)作用是把DLL中的相关代码插入到应用程序中。
_declspec(dllexport)与_declspec(dllimport)是相互呼应,只有在DLL内部用dllexport作了声明,才能在外部函数中用dllimport导入相关代码。

// pch.h: 这是预编译标头文件。
// 下方列出的文件仅编译一次,提高了将来生成的生成性能。
// 这还将影响 IntelliSense 性能,包括代码完成和许多代码浏览功能。
// 但是,如果此处列出的文件中的任何一个在生成之间有更新,它们全部都将被重新编译。
// 请勿在此处添加要频繁更新的文件,这将使得性能优势无效。

#ifndef PCH_H
#define PCH_H

// 添加要在此处预编译的标头
#include "framework.h"

#endif //PCH_H


extern "C"
{
    _declspec(dllexport) bool tcp_client_init(const char* ip, int iPort);
    _declspec(dllexport) bool tcp_client_send(char* buff, int len);
    _declspec(dllexport) int tcp_client_rcv(char* buff, int* len);
    _declspec(dllexport) int close_tcp_client();
};

3. pch.cpp文件

// pch.cpp: 与预编译标头对应的源文件

#include "pch.h"

// 当使用预编译的头时,需要使用此源文件,编译才能成功。

#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#pragma comment(lib, "ws2_32")

static SOCKET sClient;
#define CLENT_NUM 1
static SOCKET sSever, sSever_c[CLENT_NUM];
struct sockaddr_in sSever_c_sd[CLENT_NUM];

#define USER_ERROR -1

bool tcp_client_init(const char* ip, int iPort)
{
    struct sockaddr_in ser; //服务器端地址
    WSADATA wsaData;

    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
    {
        printf("Failed to load Winsock.\n"); //Winsock 初始化错误
        return false;
    }
    ser.sin_family = AF_INET;                        //初始化服务器地址信息
    ser.sin_port = htons(iPort);                     //端口转换为网络字节序
    ser.sin_addr.s_addr = inet_addr(ip); //IP 地址转换为网络字节序
    sClient = socket(AF_INET, SOCK_STREAM, 0);       //创建客户端流式套接字
    if (sClient == INVALID_SOCKET)
    {
        printf("socket() Failed: %d\n", WSAGetLastError());
        return false;
    }
    //请求与服务器端建立 TCP 连接
    if (connect(sClient, (struct sockaddr*)&ser, sizeof(ser)) == INVALID_SOCKET)
    {
        printf("connect() Failed: %d\n", WSAGetLastError());
        return false;
    }
    printf("socket connect ok\n");

    return true;
}

bool tcp_client_send(char* buff, int len)
{
    send(sClient, buff, len, 0);
    return true;
}

int tcp_client_rcv(char* buff, int* len)
{
    int iLen; //从服务器端接收的数据长度

    iLen = recv(sClient, buff, 1024, 0); //从服务器端接收数据
    if (iLen == 0)
        return -1;
    else if (iLen == SOCKET_ERROR)
    {
        printf("recv() Failed: %d\n", WSAGetLastError());
        return -1;
    }
    else
        printf("recv() data from server: %s\n", buff); // 输出接收数据
    *len = iLen;

    return iLen;
}

int close_tcp_client()
{
    closesocket(sClient); //关闭 socket
    WSACleanup();
    printf("socket close\n");
    return 0;
}

完成了这两个文件的修改,直接重新生成即可在程序文件夹内得到dll和lib

4. 使用dll和lib

直接新建一个工程,将lib文件放在工程目录,dll文件放在exe目录下
在 .h文件中添加如下

#ifdef __cplusplus

#pragma comment(lib, "TcpDll.lib")
#pragma comment(lib, "ServerTcpDLL.lib")
extern "C" {
#endif
	__declspec(dllimport) bool __stdcall tcp_client_init(const char* ip, int iPort);
	__declspec(dllimport) bool __stdcall tcp_client_send(char* buff, int len);
	__declspec(dllimport) int __stdcall tcp_client_rcv(char* buff, int* len);
	__declspec(dllimport) int __stdcall close_tcp_client();

#ifdef __cplusplus
}
#endif

做完这一步,直接在cpp内使用该函数即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值