#include "TcpipSCF.h" #include "scketfuncs.h" // 构造函数 TcpipSCF::TcpipSCF() { hCom = -1; // Linux不使用,设为-1 Connected = false; Socketfd = -1; // Linux无效套接字为-1 m_pIp = new string(); m_Port = 0; } // 析构函数 TcpipSCF::~TcpipSCF() { if (Socketfd != -1) { Disconnect(); // 确保断开连接 } delete m_pIp; } // 主机名解析 hostent* TcpipSCF::Gethostbyname(const char* name1) { hostent* he = gethostbyname(name1); if (!he) { // 尝试解析为IP地址 unsigned long ip = inet_addr(name1); if (ip != INADDR_NONE) { static hostent result; static char* addr_list[2]; static char addr[4]; memcpy(addr, &ip, 4); addr_list[0] = addr; addr_list[1] = NULL; result.h_name = (char*)name1; result.h_aliases = NULL; result.h_addrtype = AF_INET; result.h_length = 4; result.h_addr_list = addr_list; return &result; } } return he; } // 服务名解析 servent* TcpipSCF::Getservbyname(const char* name, const char* prot) { servent* se = getservbyname(name, prot); if (!se) { // 尝试解析为端口号 unsigned short port = static_cast(atoi(name)); if (port > 0) { static servent result; result.s_name = (char*)name; result.s_aliases = NULL; result.s_port = htons(port); result.s_proto = (char*)prot; return &result; } } return se; } // TCP/IP连接实现 int TcpipSCF::ConnectTcpip(const char* ip, unsigned short port, unsigned int timeout) { // 关闭现有连接 if (Socketfd != -1) { CLOSESOCKET(Socketfd); } Socketfd = -1; Connected = false; // 解析主机名 hostent* he = Gethostbyname(ip); if (!he) { return SCF_OPEN_FAILED; } // 创建套接字 Socketfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (Socketfd < 0) { return SCF_OPEN_FAILED; } // 设置为非阻塞模式 int flags = fcntl(Socketfd, F_GETFL, 0); if (fcntl(Socketfd, F_SETFL, flags | O_NONBLOCK) < 0) { CLOSESOCKET(Socketfd); return SCF_OPEN_FAILED; } // 设置地址结构 memset(&sa, 0, sizeof(sa)); sa.sin_family = AF_INET; sa.sin_port = htons(port); memcpy(&sa.sin_addr, he->h_addr, he->h_length); // 发起连接 int ret = connect(Socketfd, (sockaddr*)&sa, sizeof(sa)); if (ret == 0) { // 立即连接成功 Connected = true; socket_set_keepalive(Socketfd); // 设置keep-alive return SCF_SUCCEED; } else if (errno != EINPROGRESS) { // 连接立即失败 CLOSESOCKET(Socketfd); return SCF_OPEN_FAILED; } // 等待连接完成 fd_set wset; FD_ZERO(&wset); FD_SET(Socketfd, &wset); // 设置超时 timeval tv; tv.tv_sec = timeout / 1000; tv.tv_usec = (timeout % 1000) * 1000; ret = select(Socketfd + 1, NULL, &wset, NULL, &tv); if (ret > 0) { // 检查套接字错误状态 int error = 0; socklen_t len = sizeof(error); if (getsockopt(Socketfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0 || error != 0) { CLOSESOCKET(Socketfd); return SCF_OPEN_FAILED; } // 连接成功 Connected = true; socket_set_keepalive(Socketfd); return SCF_SUCCEED; } else if (ret == 0) { // 连接超时 CLOSESOCKET(Socketfd); return SCF_TIMEOUT; } else { // 选择错误 CLOSESOCKET(Socketfd); return SCF_OPEN_FAILED; } } // 连接接口实现 int TcpipSCF::Connect(ResDataObject& Connectprameters, PacketParser callback, SCF_TRANSFERTYPE TransferType, unsigned int CommunicateTimeout) { int ret = SCF_FAILED; InitSCF(); try { ResDataObject params = Connectprameters; params.MakeKeyLower(); string ConnectionType = static_cast(Connectprameters["type"]); string ThisType = GetConnectionType(); // 转换为小写比较 std::transform(ConnectionType.begin(), ConnectionType.end(), ConnectionType.begin(), ::tolower); std::transform(ThisType.begin(), ThisType.end(), ThisType.begin(), ::tolower); if (ConnectionType != ThisType) { return SCF_PARAMETER_ERR; } *m_pIp = static_cast(Connectprameters["ip"]); m_Port = static_cast(Connectprameters["port"]); // 建立TCP/IP连接 ret = ConnectTcpip(m_pIp->c_str(), m_Port, CommunicateTimeout); if (ret == SCF_SUCCEED) { // 连接成功后初始化SCF string NewFileName = "tcpip/" + *m_pIp + "_" + static_cast(Connectprameters["port"]); InitSCF(NewFileName.c_str()); // 调用基类连接方法 ret = SCF::Connect(Connectprameters, callback, TransferType, CommunicateTimeout); if (ret != SCF_SUCCEED) { return ret; } } } catch (...) { ret = SCF_UNKNOWN; } return ret; } // 断开连接 void TcpipSCF::Disconnect() { SCF::Disconnect(); // 调用基类断开方法 if (Socketfd != -1) { CLOSESOCKET(Socketfd); // 安全关闭套接字 Connected = false; } } // 检查连接状态 bool TcpipSCF::isConnected() { return (Socketfd != -1); // 套接字有效表示连接存在 } // 获取连接类型 const char* TcpipSCF::GetConnectionType() { static string nType = "TCPIP"; return nType.c_str(); } // 发送SCF数据包 int TcpipSCF::SendPacket(SCFPacket* pPacket, unsigned int timeout) { return SendPacket((char*)(*pPacket), pPacket->GetPacketLen(), timeout); } // 发送原始数据 int TcpipSCF::SendPacket(const char* pPacket, unsigned int length, unsigned int timeout) { if (!isConnected()) { return SCF_DISCONNETED; } unsigned int Posted = 0; timeval tv; tv.tv_sec = timeout / 1000; tv.tv_usec = (timeout % 1000) * 1000; // 分段发送数据 while (Posted < length) { fd_set wset; FD_ZERO(&wset); FD_SET(Socketfd, &wset); // 等待套接字可写 int ret = select(Socketfd + 1, NULL, &wset, NULL, &tv); if (ret > 0) { // 发送数据 int OneShot = send(Socketfd, pPacket + Posted, length - Posted, 0); if (OneShot > 0) { Posted += OneShot; // 更新已发送字节数 } else if (OneShot == 0) { return SCF_WRITE_FAILED; // 连接已关闭 } else { // 处理错误 if (errno == EAGAIN || errno == EWOULDBLOCK) { continue; // 重试 } PassiveDisconnected(); return SCF_WRITE_FAILED; } } else if (ret == 0) { return SCF_TIMEOUT; // 发送超时 } else { return SCF_WRITE_FAILED; // 发送错误 } } return SCF_SUCCEED; // 发送成功 } // 读取数据 int TcpipSCF::ReadData(char* pPacket, unsigned int length, unsigned int timeout) { if (!isConnected()) { return SCF_DISCONNETED; } fd_set fds; FD_ZERO(&fds); FD_SET(Socketfd, &fds); // 设置超时 timeval tv; tv.tv_sec = timeout / 1000; tv.tv_usec = (timeout % 1000) * 1000; // 等待数据可读 int ret = select(Socketfd + 1, &fds, NULL, NULL, &tv); if (ret > 0) { // 读取数据 int count = recv(Socketfd, pPacket, length, 0); if (count > 0) { return count; // 返回读取的字节数 } else if (count == 0) { PassiveDisconnected(); return SCF_DISCONNETED; // 连接关闭 } else { // 处理错误 if (errno == EAGAIN || errno == EWOULDBLOCK) { return SCF_TIMEOUT; // 读取超时 } PassiveDisconnected(); return SCF_READ_FAILED; // 读取错误 } } else if (ret == 0) { return SCF_TIMEOUT; // 超时 } else { return SCF_READ_FAILED; // 选择错误 } } // 创建SCF实例 TCPIPSCF_C_API SCF* GetSCF() { return new TcpipSCF(); } // 释放SCF实例 TCPIPSCF_C_API void ReleseSCF(SCF* p) { delete p; }