///////////////////////////////////////////////////////////////// // SocketServer.cpp - Demonstrate basics of socket code // // - handles both IPv4 and IPv6 // // // // Jim Fawcett, CSE687 - Object Oriented Design, Spring 2015 // ///////////////////////////////////////////////////////////////// #undef UNICODE #define WIN32_LEAN_AND_MEAN // prevents code duplication in winsock2.h #include // Windnows API #include // Windows sockets, ver 2 #include // support for IPv6 and other things #include // ip helpers #include "../ApplicationHelpers/AppHelpers.h" #include "../WindowsHelpers/WindowsHelpers.h" #include #pragma comment (lib, "Ws2_32.lib") // link to Winsock library #define DEFAULT_BUFLEN 512 #define DEFAULT_PORT "27015" using namespace ApplicationHelpers; using namespace WindowsHelpers; //----< this doesn't work as expected - left here to fix sometime >---------- void displayAddress(struct addrinfo* pResult) { char ipstr[INET6_ADDRSTRLEN]; void *addr; char *ipver; // get the pointer to the address itself, // different fields in IPv4 and IPv6: if (pResult->ai_family == AF_INET) { // IPv4 struct sockaddr_in *ipv4 = (struct sockaddr_in *)pResult->ai_addr; addr = &(ipv4->sin_addr); ipver = "IPv4"; } else { // IPv6 struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)pResult->ai_addr; addr = &(ipv6->sin6_addr); ipver = "IPv6"; } // convert the IP to a string and print it: inet_ntop(pResult->ai_family, addr, ipstr, sizeof ipstr); printf(" %s: %s\n", ipver, ipstr); } //----< entry point >-------------------------------------------------------- int main(void) { title("Socket Server", '='); WSADATA wsaData; int iResult; SOCKET ListenSocket = INVALID_SOCKET; SOCKET ClientSocket = INVALID_SOCKET; struct addrinfo *result = NULL; struct addrinfo hints; int iSendResult; char recvbuf[DEFAULT_BUFLEN]; int recvbuflen = DEFAULT_BUFLEN; const char* yes = "1"; // Initialize Winsock iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); if (iResult != 0) { std::cout << "\n WSAStartup failed with error: " << iResult << "\n\n"; return 1; } ZeroMemory(&hints, sizeof(hints)); //hints.ai_family = AF_INET; // use this if you want an IP4 address hints.ai_family = AF_INET6; // use this if you want an IP6 address //hints.ai_family = AF_UNSPEC; // don't use this - ok for client hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; hints.ai_flags = AI_PASSIVE; // Resolve the server address and port iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result); if (iResult != 0) { std::cout << "\n getaddrinfo failed with error: " << iResult << "\n\n"; WSACleanup(); return 1; } // Iterate through all results and bind to first available for (auto pResult = result; pResult != NULL; pResult = pResult->ai_next) { // Create a SOCKET for connecting to server ListenSocket = socket(pResult->ai_family, pResult->ai_socktype, pResult->ai_protocol); if (ListenSocket == INVALID_SOCKET) { std::cout << "\n socket failed with error: " << WSAGetLastError() << "\n\n"; continue; } std::cout << "\n Created ListenSocket"; // Setup the TCP listening socket iResult = bind(ListenSocket, pResult->ai_addr, (int)pResult->ai_addrlen); if (iResult == SOCKET_ERROR) { std::cout << "\n bind failed with error: " << GetLastMsg(true) << "\n\n"; closesocket(ListenSocket); continue; } else { break; } } //displayAddress(result); freeaddrinfo(result); std::cout << "\n TCP listening socket setup"; iResult = listen(ListenSocket, SOMAXCONN); if (iResult == SOCKET_ERROR) { std::cout << "\n listen failed with error: " << WSAGetLastError() << "\n\n"; closesocket(ListenSocket); WSACleanup(); return 1; } //std::cout << "\n waiting for connection"; // Accept a client socket - blocking call ClientSocket = accept(ListenSocket, NULL, NULL); if (ClientSocket == INVALID_SOCKET) { std::cout << "\n accept failed with error: " << WSAGetLastError() << "\n\n"; closesocket(ListenSocket); WSACleanup(); return 1; } std::cout << "\n accepted connection\n"; // No longer need server socket closesocket(ListenSocket); // Receive until the peer shuts down the connection do { iResult = recv(ClientSocket, recvbuf, recvbuflen, 0); if (iResult > 0) { std::cout << "\n Bytes received: " << iResult; if (iResult < recvbuflen) recvbuf[iResult] = '\0'; else recvbuf[recvbuflen - 1] = '\0'; std::string msg = std::string(recvbuf); std::cout << "\n " << msg; // Echo the buffer back to the sender iSendResult = send(ClientSocket, recvbuf, iResult+1, 0); if (iSendResult == SOCKET_ERROR) { std::cout << "\n send failed with error: " << WSAGetLastError() << "\n\n"; closesocket(ClientSocket); WSACleanup(); return 1; } std::cout << "\n Bytes sent: " << iSendResult; } else if (iResult == 0) std::cout << "\n Connection closing...\n"; else { std::cout << "\n recv failed with error: " << WSAGetLastError() << "\n\n"; closesocket(ClientSocket); WSACleanup(); return 1; } } while (iResult > 0); // shutdown the connection since we're done iResult = shutdown(ClientSocket, SD_SEND); if (iResult == SOCKET_ERROR) { std::cout << "\n shutdown failed with error: " << WSAGetLastError() << "\n\n"; closesocket(ClientSocket); WSACleanup(); return 1; } // cleanup closesocket(ClientSocket); WSACleanup(); std::cout << "\n"; return 0; }