123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320 |
- #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<unsigned short>(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<const char*>(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<const char*>(Connectprameters["ip"]);
- m_Port = static_cast<unsigned short>(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<const char*>(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;
- }
|