myicqhttp.cpp
上传用户:zslianheng
上传日期:2013-04-03
资源大小:946k
文件大小:4k
源码类别:

Linux/Unix编程

开发平台:

Visual C++

  1. /***************************************************************************
  2.  *                                                                         *
  3.  *   This program is free software; you can redistribute it and/or modify  *
  4.  *   it under the terms of the GNU General Public License as published by  *
  5.  *   the Free Software Foundation; either version 2 of the License, or     *
  6.  *   (at your option) any later version.                                   *
  7.  *                                                                         *
  8.  *   copyright            : (C) 2002 by Zhang Yong                         *
  9.  *   email                : z-yong163@163.com                              *
  10.  ***************************************************************************/
  11. #ifdef _WIN32
  12. #include <windows.h>
  13. #define close closesocket
  14. typedef int socklen_t;
  15. #else
  16. #include <unistd.h>
  17. #include <sys/types.h>
  18. #include <sys/socket.h>
  19. #include <netinet/in.h>
  20. #endif
  21. #include <iostream.h>
  22. #define MYICQ_HTTP_PORT 443
  23. #define MYICQ_PORT 8000
  24. #define MAX_PACKET_SIZE 4096
  25. typedef unsigned short uint16;
  26. typedef unsigned int uint32;
  27. inline int getSocketError()
  28. {
  29. #ifdef _WIN32
  30. return WSAGetLastError();
  31. #else
  32. return errno;
  33. #endif
  34. }
  35. static sockaddr_in destAddr;
  36. static int onHttpReceive(int httpSock, int udpSock, char *buf, int &bufSize)
  37. {
  38. int n = recv(httpSock, buf + bufSize, MAX_PACKET_SIZE - bufSize, 0);
  39. if (n > 0) {
  40. bufSize += n;
  41. char *start = buf;
  42. char *end = start + bufSize;
  43. uint16 len;
  44. while (start + sizeof(len) < end) {
  45. len = ntohs(*(uint16 *) start);
  46. if (end - start - sizeof(len) < len)
  47. break;
  48. start += sizeof(len);
  49. send(udpSock, start, len, 0);
  50. start += len;
  51. }
  52. bufSize = end - start;
  53. if (bufSize > 0)
  54. memcpy(buf, start, bufSize);
  55. }
  56. return n;
  57. }
  58. static int onUdpReceive(int httpSock, int udpSock)
  59. {
  60. char buf[MAX_PACKET_SIZE];
  61. int n = recv(udpSock, buf + sizeof(uint16), MAX_PACKET_SIZE - sizeof(uint16), 0);
  62. if (n > 0) {
  63. *(uint16 *) buf = htons(n);
  64. send(httpSock, buf, n + sizeof(uint16), 0);
  65. }
  66. return n;
  67. }
  68. static DWORD WINAPI processRequest(LPVOID param)
  69. {
  70. int httpSock = (int) param;
  71. int udpSock = socket(AF_INET, SOCK_DGRAM, 0);
  72. if (udpSock < 0) {
  73. close(httpSock);
  74. return 1;
  75. }
  76. connect(udpSock, (sockaddr *) &destAddr, sizeof(destAddr));
  77. char buf[MAX_PACKET_SIZE];
  78. int bufSize = 0;
  79. int nfds = (httpSock > udpSock ? httpSock : udpSock);
  80. fd_set rdset;
  81. while (true) {
  82. FD_ZERO(&rdset);
  83. FD_SET(httpSock, &rdset);
  84. FD_SET(udpSock, &rdset);
  85. if (select(nfds + 1, &rdset, NULL, NULL, NULL) < 0)
  86. break;
  87. if (FD_ISSET(httpSock, &rdset) &&
  88. onHttpReceive(httpSock, udpSock, buf, bufSize) <= 0)
  89. break;
  90. if (FD_ISSET(udpSock, &rdset) &&
  91. onUdpReceive(httpSock, udpSock) <= 0)
  92. break;
  93. }
  94. close(udpSock);
  95. close(httpSock);
  96. return 0;
  97. }
  98. int main(int argc, char *argv[])
  99. {
  100. #ifdef _WIN32
  101. WSADATA wsaData;
  102. WORD version = MAKEWORD(2, 2);
  103. if (WSAStartup(version, &wsaData) != 0) {
  104. cerr << "WSAStartup() failed." << endl;
  105. return 1;
  106. }
  107. #endif
  108. const char *host = "localhost";
  109. uint16 port = MYICQ_PORT;
  110. if (argc > 1)
  111. host = argv[1];
  112. if (argc > 2)
  113. port = atoi(argv[2]);
  114. memset(&destAddr, 0, sizeof(destAddr));
  115. destAddr.sin_family = AF_INET;
  116. if ((destAddr.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE) {
  117. hostent *he = gethostbyname(host);
  118. if (!he) {
  119. cerr << "Can not resolve host: " << host << endl;
  120. return 1;
  121. }
  122. destAddr.sin_addr = *(in_addr *) he->h_addr;
  123. }
  124. destAddr.sin_port = htons(port);
  125. int listen_fd = socket(AF_INET, SOCK_STREAM, 0);
  126. sockaddr_in addr;
  127. memset(&addr, 0, sizeof(addr));
  128. addr.sin_family = AF_INET;
  129. addr.sin_addr.s_addr = INADDR_ANY;
  130. addr.sin_port = htons(MYICQ_HTTP_PORT);
  131. if (bind(listen_fd, (sockaddr *) &addr, sizeof(addr)) < 0) {
  132. cerr << "Can not bind on port: " << MYICQ_HTTP_PORT << endl;
  133. close(listen_fd);
  134. return 1;
  135. }
  136. listen(listen_fd, 20);
  137. cout << "MyICQ http server is now started." << endl;
  138. while (true) {
  139. socklen_t addrlen = sizeof(addr);
  140. int new_fd = accept(listen_fd, (sockaddr *) &addr, &addrlen);
  141. if (new_fd >= 0) {
  142. DWORD id;
  143. CreateThread(NULL, 0, processRequest, (LPVOID) new_fd, 0, &id);
  144. }
  145. }
  146. close(listen_fd);
  147. #ifdef _WIN32
  148. WSACleanup();
  149. #endif
  150. return 0;
  151. }