socketio_win32.cpp 5.5 KB

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