TcpipSCF.cpp 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. #include "TcpipSCF.h"
  2. #include "scketfuncs.h"
  3. // 构造函数
  4. TcpipSCF::TcpipSCF() {
  5. hCom = -1; // Linux不使用,设为-1
  6. Connected = false;
  7. Socketfd = -1; // Linux无效套接字为-1
  8. m_pIp = new string();
  9. m_Port = 0;
  10. }
  11. // 析构函数
  12. TcpipSCF::~TcpipSCF() {
  13. if (Socketfd != -1) {
  14. Disconnect(); // 确保断开连接
  15. }
  16. delete m_pIp;
  17. }
  18. // 主机名解析
  19. hostent* TcpipSCF::Gethostbyname(const char* name1) {
  20. hostent* he = gethostbyname(name1);
  21. if (!he) {
  22. // 尝试解析为IP地址
  23. unsigned long ip = inet_addr(name1);
  24. if (ip != INADDR_NONE) {
  25. static hostent result;
  26. static char* addr_list[2];
  27. static char addr[4];
  28. memcpy(addr, &ip, 4);
  29. addr_list[0] = addr;
  30. addr_list[1] = NULL;
  31. result.h_name = (char*)name1;
  32. result.h_aliases = NULL;
  33. result.h_addrtype = AF_INET;
  34. result.h_length = 4;
  35. result.h_addr_list = addr_list;
  36. return &result;
  37. }
  38. }
  39. return he;
  40. }
  41. // 服务名解析
  42. servent* TcpipSCF::Getservbyname(const char* name, const char* prot) {
  43. servent* se = getservbyname(name, prot);
  44. if (!se) {
  45. // 尝试解析为端口号
  46. unsigned short port = static_cast<unsigned short>(atoi(name));
  47. if (port > 0) {
  48. static servent result;
  49. result.s_name = (char*)name;
  50. result.s_aliases = NULL;
  51. result.s_port = htons(port);
  52. result.s_proto = (char*)prot;
  53. return &result;
  54. }
  55. }
  56. return se;
  57. }
  58. // TCP/IP连接实现
  59. int TcpipSCF::ConnectTcpip(const char* ip, unsigned short port, unsigned int timeout) {
  60. // 关闭现有连接
  61. if (Socketfd != -1) {
  62. CLOSESOCKET(Socketfd);
  63. }
  64. Socketfd = -1;
  65. Connected = false;
  66. // 解析主机名
  67. hostent* he = Gethostbyname(ip);
  68. if (!he) {
  69. return SCF_OPEN_FAILED;
  70. }
  71. // 创建套接字
  72. Socketfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  73. if (Socketfd < 0) {
  74. return SCF_OPEN_FAILED;
  75. }
  76. // 设置为非阻塞模式
  77. int flags = fcntl(Socketfd, F_GETFL, 0);
  78. if (fcntl(Socketfd, F_SETFL, flags | O_NONBLOCK) < 0) {
  79. CLOSESOCKET(Socketfd);
  80. return SCF_OPEN_FAILED;
  81. }
  82. // 设置地址结构
  83. memset(&sa, 0, sizeof(sa));
  84. sa.sin_family = AF_INET;
  85. sa.sin_port = htons(port);
  86. memcpy(&sa.sin_addr, he->h_addr, he->h_length);
  87. // 发起连接
  88. int ret = connect(Socketfd, (sockaddr*)&sa, sizeof(sa));
  89. if (ret == 0) {
  90. // 立即连接成功
  91. Connected = true;
  92. socket_set_keepalive(Socketfd); // 设置keep-alive
  93. return SCF_SUCCEED;
  94. }
  95. else if (errno != EINPROGRESS) {
  96. // 连接立即失败
  97. CLOSESOCKET(Socketfd);
  98. return SCF_OPEN_FAILED;
  99. }
  100. // 等待连接完成
  101. fd_set wset;
  102. FD_ZERO(&wset);
  103. FD_SET(Socketfd, &wset);
  104. // 设置超时
  105. timeval tv;
  106. tv.tv_sec = timeout / 1000;
  107. tv.tv_usec = (timeout % 1000) * 1000;
  108. ret = select(Socketfd + 1, NULL, &wset, NULL, &tv);
  109. if (ret > 0) {
  110. // 检查套接字错误状态
  111. int error = 0;
  112. socklen_t len = sizeof(error);
  113. if (getsockopt(Socketfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0 || error != 0) {
  114. CLOSESOCKET(Socketfd);
  115. return SCF_OPEN_FAILED;
  116. }
  117. // 连接成功
  118. Connected = true;
  119. socket_set_keepalive(Socketfd);
  120. return SCF_SUCCEED;
  121. }
  122. else if (ret == 0) {
  123. // 连接超时
  124. CLOSESOCKET(Socketfd);
  125. return SCF_TIMEOUT;
  126. }
  127. else {
  128. // 选择错误
  129. CLOSESOCKET(Socketfd);
  130. return SCF_OPEN_FAILED;
  131. }
  132. }
  133. // 连接接口实现
  134. int TcpipSCF::Connect(ResDataObject& Connectprameters, PacketParser callback,
  135. SCF_TRANSFERTYPE TransferType, unsigned int CommunicateTimeout) {
  136. int ret = SCF_FAILED;
  137. InitSCF();
  138. try {
  139. ResDataObject params = Connectprameters;
  140. params.MakeKeyLower();
  141. string ConnectionType = static_cast<const char*>(Connectprameters["type"]);
  142. string ThisType = GetConnectionType();
  143. // 转换为小写比较
  144. std::transform(ConnectionType.begin(), ConnectionType.end(), ConnectionType.begin(), ::tolower);
  145. std::transform(ThisType.begin(), ThisType.end(), ThisType.begin(), ::tolower);
  146. if (ConnectionType != ThisType) {
  147. return SCF_PARAMETER_ERR;
  148. }
  149. *m_pIp = static_cast<const char*>(Connectprameters["ip"]);
  150. m_Port = static_cast<unsigned short>(Connectprameters["port"]);
  151. // 建立TCP/IP连接
  152. ret = ConnectTcpip(m_pIp->c_str(), m_Port, CommunicateTimeout);
  153. if (ret == SCF_SUCCEED) {
  154. // 连接成功后初始化SCF
  155. string NewFileName = "tcpip/" + *m_pIp + "_" + static_cast<const char*>(Connectprameters["port"]);
  156. InitSCF(NewFileName.c_str());
  157. // 调用基类连接方法
  158. ret = SCF::Connect(Connectprameters, callback, TransferType, CommunicateTimeout);
  159. if (ret != SCF_SUCCEED) {
  160. return ret;
  161. }
  162. }
  163. }
  164. catch (...) {
  165. ret = SCF_UNKNOWN;
  166. }
  167. return ret;
  168. }
  169. // 断开连接
  170. void TcpipSCF::Disconnect() {
  171. SCF::Disconnect(); // 调用基类断开方法
  172. if (Socketfd != -1) {
  173. CLOSESOCKET(Socketfd); // 安全关闭套接字
  174. Connected = false;
  175. }
  176. }
  177. // 检查连接状态
  178. bool TcpipSCF::isConnected() {
  179. return (Socketfd != -1); // 套接字有效表示连接存在
  180. }
  181. // 获取连接类型
  182. const char* TcpipSCF::GetConnectionType() {
  183. static string nType = "TCPIP";
  184. return nType.c_str();
  185. }
  186. // 发送SCF数据包
  187. int TcpipSCF::SendPacket(SCFPacket* pPacket, unsigned int timeout) {
  188. return SendPacket((char*)(*pPacket), pPacket->GetPacketLen(), timeout);
  189. }
  190. // 发送原始数据
  191. int TcpipSCF::SendPacket(const char* pPacket, unsigned int length, unsigned int timeout) {
  192. if (!isConnected()) {
  193. return SCF_DISCONNETED;
  194. }
  195. unsigned int Posted = 0;
  196. timeval tv;
  197. tv.tv_sec = timeout / 1000;
  198. tv.tv_usec = (timeout % 1000) * 1000;
  199. // 分段发送数据
  200. while (Posted < length) {
  201. fd_set wset;
  202. FD_ZERO(&wset);
  203. FD_SET(Socketfd, &wset);
  204. // 等待套接字可写
  205. int ret = select(Socketfd + 1, NULL, &wset, NULL, &tv);
  206. if (ret > 0) {
  207. // 发送数据
  208. int OneShot = send(Socketfd, pPacket + Posted, length - Posted, 0);
  209. if (OneShot > 0) {
  210. Posted += OneShot; // 更新已发送字节数
  211. }
  212. else if (OneShot == 0) {
  213. return SCF_WRITE_FAILED; // 连接已关闭
  214. }
  215. else {
  216. // 处理错误
  217. if (errno == EAGAIN || errno == EWOULDBLOCK) {
  218. continue; // 重试
  219. }
  220. PassiveDisconnected();
  221. return SCF_WRITE_FAILED;
  222. }
  223. }
  224. else if (ret == 0) {
  225. return SCF_TIMEOUT; // 发送超时
  226. }
  227. else {
  228. return SCF_WRITE_FAILED; // 发送错误
  229. }
  230. }
  231. return SCF_SUCCEED; // 发送成功
  232. }
  233. // 读取数据
  234. int TcpipSCF::ReadData(char* pPacket, unsigned int length, unsigned int timeout) {
  235. if (!isConnected()) {
  236. return SCF_DISCONNETED;
  237. }
  238. fd_set fds;
  239. FD_ZERO(&fds);
  240. FD_SET(Socketfd, &fds);
  241. // 设置超时
  242. timeval tv;
  243. tv.tv_sec = timeout / 1000;
  244. tv.tv_usec = (timeout % 1000) * 1000;
  245. // 等待数据可读
  246. int ret = select(Socketfd + 1, &fds, NULL, NULL, &tv);
  247. if (ret > 0) {
  248. // 读取数据
  249. int count = recv(Socketfd, pPacket, length, 0);
  250. if (count > 0) {
  251. return count; // 返回读取的字节数
  252. }
  253. else if (count == 0) {
  254. PassiveDisconnected();
  255. return SCF_DISCONNETED; // 连接关闭
  256. }
  257. else {
  258. // 处理错误
  259. if (errno == EAGAIN || errno == EWOULDBLOCK) {
  260. return SCF_TIMEOUT; // 读取超时
  261. }
  262. PassiveDisconnected();
  263. return SCF_READ_FAILED; // 读取错误
  264. }
  265. }
  266. else if (ret == 0) {
  267. return SCF_TIMEOUT; // 超时
  268. }
  269. else {
  270. return SCF_READ_FAILED; // 选择错误
  271. }
  272. }
  273. // 创建SCF实例
  274. TCPIPSCF_C_API SCF* GetSCF() {
  275. return new TcpipSCF();
  276. }
  277. // 释放SCF实例
  278. TCPIPSCF_C_API void ReleseSCF(SCF* p) {
  279. delete p;
  280. }