socketio_win32.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. #include "socketio.hpp"
  2. #include <stdio.h>
  3. #include <cstdint>
  4. #include <cinttypes>
  5. #include <winsock2.h>
  6. #include <ws2tcpip.h>
  7. #pragma comment(lib, "ws2_32.lib")
  8. #include <string>
  9. #include <cstring>
  10. #include <vector>
  11. #include <iostream>
  12. #ifdef _MSC_VER
  13. #undef min
  14. #ifdef _WIN64
  15. using ssize_t = std::int64_t;
  16. #endif
  17. #ifndef _WIN64
  18. using ssize_t = std::int32_t;
  19. #endif
  20. template<typename T>
  21. const T& min(const T& a,const T& b){
  22. return (b < a) ? b : a;
  23. }
  24. #else
  25. using std::min;
  26. #endif
  27. using std::size_t;
  28. struct socket_exception : public std::exception {
  29. std::string msg;
  30. socket_exception(std::string&& _msg) {
  31. msg = std::move(_msg);
  32. }
  33. socket_exception(const std::string& _msg) {
  34. msg = _msg;
  35. }
  36. socket_exception(const char* _msg) {
  37. msg = std::string(_msg);
  38. }
  39. const virtual char* what() const throw () {
  40. //return "asdasdsa";
  41. return msg.length() == 0 ? "Connection creation failure" : msg.c_str();
  42. }
  43. };
  44. std::string GetLastErrorAsString() {
  45. //Get the error message, if any.
  46. DWORD errorMessageID = ::GetLastError();
  47. if (errorMessageID == 0)
  48. return std::string();
  49. LPSTR messageBuffer = nullptr;
  50. size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
  51. NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);
  52. std::string message(messageBuffer, size);
  53. //Free the buffer.
  54. LocalFree(messageBuffer);
  55. return message;
  56. }
  57. cppsocket::cppsocket() {
  58. buffer = std::vector<char>(buffersize + 1, 0);
  59. }
  60. cppsocket::cppsocket(cppsocket&& o) {
  61. s = o.s;
  62. o.s = INVALID_SOCKET;
  63. buffer = std::move(o.buffer);
  64. }
  65. cppsocket::cppsocket(WSADATA d, SOCKET _s) {
  66. s = _s;
  67. wsa = d;
  68. buffer = std::vector<char>(buffersize + 1, 0);
  69. }
  70. cppsocket::cppsocket(const std::string& addr, unsigned int PORT) {
  71. struct sockaddr_in server;
  72. buffer = std::vector<char>(buffersize + 1, 0);
  73. int recv_size;
  74. if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) {
  75. throw socket_exception(std::string("Socket creation error: ") + GetLastErrorAsString());
  76. }
  77. if ((s = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
  78. throw socket_exception(std::string("Socket creation error: ") + GetLastErrorAsString());
  79. }
  80. server.sin_addr.s_addr = inet_addr(addr.c_str());
  81. server.sin_family = AF_INET;
  82. server.sin_port = htons(PORT);
  83. if (connect(s, (struct sockaddr *)&server, sizeof(server)) < 0) {
  84. throw socket_exception(std::string("Could not connect to host: ") + GetLastErrorAsString());
  85. }
  86. }
  87. void cppsocket::write(const std::string& message) {
  88. std::vector<char> msg(message.c_str(), message.c_str() + message.size());
  89. write(msg);
  90. }
  91. void cppsocket::write(const std::vector<char>& message) {
  92. for (size_t i = 0; i < message.size(); i += buffersize) {
  93. char cs[buffersize + 1] = { 0 };
  94. std::memcpy(cs, message.data() + i, buffersize);
  95. if ((i + buffersize) < message.size()) {
  96. cs[buffersize] = 'c';
  97. if (send(s, cs, buffersize + 1, 0) < 0) {
  98. throw socket_exception(std::string("Couldn't write to peer: ") + GetLastErrorAsString());
  99. }
  100. }
  101. else {
  102. cs[message.size() - i] = (char)0;
  103. if (send(s, cs, message.size() - i, 0) < 0) {
  104. throw socket_exception(std::string("Couldn't write to peer: ") + GetLastErrorAsString());
  105. }
  106. }
  107. }
  108. }
  109. std::vector<char> cppsocket::receive() {
  110. std::vector<char> stor;
  111. while (true) {
  112. std::fill(buffer.begin(), buffer.end(), (char)0);
  113. ssize_t val = recv(s, buffer.data(), buffersize + 1, 0);
  114. if (val == 0)throw socket_exception("Connection closed by peer");
  115. if (val < 0) {
  116. throw socket_exception(GetLastErrorAsString());
  117. }
  118. stor.insert(stor.end(), buffer.begin(), buffer.begin() + min(val, (ssize_t)buffersize));
  119. if (buffer.data()[buffersize] == (char)0) { break; }
  120. }
  121. std::cout << std::endl;
  122. return stor;
  123. }
  124. void cppsocket::close() {
  125. closesocket(s);
  126. }
  127. server_socket::server_socket(int port) {
  128. struct addrinfo *result = NULL;
  129. struct addrinfo hints;
  130. iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
  131. if (iResult != 0) {
  132. printf("WSAStartup failed with error: %d\n", iResult);
  133. }
  134. ZeroMemory(&hints, sizeof(hints));
  135. hints.ai_family = AF_INET;
  136. hints.ai_socktype = SOCK_STREAM;
  137. hints.ai_protocol = IPPROTO_TCP;
  138. hints.ai_flags = AI_PASSIVE;
  139. // Resolve the server address and port
  140. iResult = getaddrinfo(NULL, std::to_string(port).c_str(), &hints, &result);
  141. if (iResult != 0) {
  142. printf("getaddrinfo failed with error: %d\n", iResult);
  143. WSACleanup();
  144. }
  145. // Create a SOCKET for connecting to server
  146. ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
  147. if (ListenSocket == INVALID_SOCKET) {
  148. printf("socket failed with error: %ld\n", WSAGetLastError());
  149. freeaddrinfo(result);
  150. WSACleanup();
  151. }
  152. // Setup the TCP listening socket
  153. iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen);
  154. if (iResult == SOCKET_ERROR) {
  155. printf("bind failed with error: %d\n", WSAGetLastError());
  156. freeaddrinfo(result);
  157. closesocket(ListenSocket);
  158. WSACleanup();
  159. }
  160. freeaddrinfo(result);
  161. iResult = listen(ListenSocket, SOMAXCONN);
  162. if (iResult == SOCKET_ERROR) {
  163. printf("listen failed with error: %d\n", WSAGetLastError());
  164. closesocket(ListenSocket);
  165. WSACleanup();
  166. }
  167. }
  168. cppsocket server_socket::accept_connection() {
  169. SOCKET ClientSocket = accept(ListenSocket, NULL, NULL);
  170. if (ClientSocket == INVALID_SOCKET) {
  171. printf("accept failed with error: %d\n", WSAGetLastError());
  172. closesocket(ListenSocket);
  173. WSACleanup();
  174. }
  175. return cppsocket(wsaData, ClientSocket);
  176. }
  177. void server_socket::close() {
  178. closesocket(ListenSocket);
  179. }
  180. cppsocket& cppsocket::operator=(cppsocket&& o) {
  181. s = o.s;
  182. o.s = INVALID_SOCKET;
  183. buffer = std::move(o.buffer);
  184. return *this;
  185. }