ServerSocket.cpp
上传用户:market2
上传日期:2018-11-18
资源大小:18786k
文件大小:4k
源码类别:

外挂编程

开发平台:

Windows_Unix

  1. /*
  2.  *  OpenKore C++ Standard Library
  3.  *  Copyright (C) 2006,2007  VCL
  4.  *
  5.  *  This library is free software; you can redistribute it and/or
  6.  *  modify it under the terms of the GNU Lesser General Public
  7.  *  License as published by the Free Software Foundation; either
  8.  *  version 2.1 of the License, or (at your option) any later version.
  9.  *
  10.  *  This library is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  *  Lesser General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU Lesser General Public
  16.  *  License along with this library; if not, write to the Free Software
  17.  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  18.  *  MA  02110-1301  USA
  19.  */
  20. // Do not compile this file independently, it's supposed to be automatically
  21. // included by another source file.
  22. #include <netinet/in.h>
  23. #include <arpa/inet.h>
  24. #include <sys/poll.h>
  25. #include <errno.h>
  26. #include <stdio.h>
  27. #include <string.h>
  28. #include <assert.h>
  29. #define DEFAULT_BACKLOG_SIZE 5
  30. class UnixServerSocket: public ServerSocket {
  31. private:
  32. /** The server socket file descriptor. */
  33. int fd;
  34. /**
  35.  * The server socket's port.
  36.  * @invariant port > 0
  37.  */
  38. unsigned short port;
  39. public:
  40. UnixServerSocket(const char *address, unsigned short port) {
  41. fd = socket(PF_INET, SOCK_STREAM, 0);
  42. if (fd == -1) {
  43. throw SocketException(strerror(errno), errno);
  44. }
  45. int on = 1;
  46. setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
  47. struct sockaddr_in addr;
  48. char *c_address = NULL;
  49. addr.sin_family = AF_INET;
  50. addr.sin_port = htons (port);
  51. if (address == NULL) {
  52. addr.sin_addr.s_addr = htonl(INADDR_ANY);
  53. } else {
  54. c_address = strdup(address);
  55. addr.sin_addr.s_addr = inet_addr(c_address);
  56. }
  57. if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1) {
  58. char message[200];
  59. snprintf(message, sizeof(message),
  60. "Cannot bind to %s:%d: %s",
  61. (address != NULL) ? address : "0.0.0.0",
  62. port, strerror(errno));
  63. ::close(fd);
  64. throw SocketException(message, errno);
  65. }
  66. if (c_address != NULL) {
  67. free(c_address);
  68. }
  69. if (port == 0) {
  70. socklen_t len = sizeof(addr);
  71. if (getsockname(fd, (struct sockaddr *) &addr, &len) == -1) {
  72. int error = errno;
  73. ::close(fd);
  74. throw SocketException("Cannot determine server socket port.", error);
  75. }
  76. this->port = ntohs(addr.sin_port);
  77. } else {
  78. this->port = port;
  79. }
  80. if (listen(fd, DEFAULT_BACKLOG_SIZE) == -1) {
  81. char message[200];
  82. snprintf(message, sizeof(message),
  83. "Cannot listen for connections on socket: %s",
  84. strerror(errno));
  85. ::close(fd);
  86. throw SocketException(message, errno);
  87. }
  88. }
  89. ~UnixServerSocket() {
  90. close();
  91. }
  92. virtual Socket *accept(int timeout) {
  93. assert(timeout >= -1);
  94. if (fd == -1) {
  95. throw IOException("Server socket is closed.");
  96. }
  97. if (timeout > -1) {
  98. struct pollfd ufds;
  99. int result;
  100. ufds.fd = fd;
  101. ufds.events = POLLIN | POLLERR | POLLHUP | POLLNVAL;
  102. result = poll(&ufds, 1, timeout);
  103. if (result == 0) {
  104. return NULL;
  105. } else if (result == -1) {
  106. throw IOException(strerror(errno), errno);
  107. } else if (ufds.revents & POLLERR) {
  108. throw IOException("A socket error condition occured.");
  109. } else if (ufds.revents & POLLHUP) {
  110. throw IOException("Server socket is closed.");
  111. } else if (ufds.revents & POLLNVAL) {
  112. throw IOException("Invalid file descriptor.");
  113. }
  114. }
  115. struct sockaddr_in addr;
  116. socklen_t len = sizeof(addr);
  117. int clientfd = ::accept(fd, (struct sockaddr *) &addr, &len);
  118. if (clientfd == -1) {
  119. throw IOException(strerror(errno), errno);
  120. }
  121. return new UnixSocket(clientfd);
  122. }
  123. virtual void close() {
  124. if (fd != -1) {
  125. ::close(fd);
  126. fd = -1;
  127. }
  128. }
  129. virtual unsigned short getPort() {
  130. return port;
  131. }
  132. virtual bool isClosed() {
  133. return fd == -1;
  134. }
  135. };