#include #include #include #define ERRMSG_BUFFER_SIZE 100 // Size of error message buffer #define LISTEN_PORT 1234 // Port we accept connections on #define BUFFER_SIZE 1024 // Size of buffer for receiving data /* Name: getErrorMsg * Desription: Returns a human readable error message for codes from * WSAGetLastError or GetLastError * Parameters: code - error code to return message for * Return code: Pointer to a static buffer containing the message * Notes: Not thread-safe because of static buffer */ const char *getErrorMsg(int code) { static char buffer[ERRMSG_BUFFER_SIZE]; FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, code, 0, buffer, sizeof(buffer), NULL); return buffer; } /* Name: initWinsock * Desription: Initialized Winsock subsystem * Parameters: none * Return code: true if successful * false if an error occurred */ bool initWinsock(void) { bool failed = false; WSADATA wsa; int startupResult = WSAStartup(MAKEWORD(1, 1), &wsa); if (startupResult != 0) { fprintf(stderr, "Couldn't start Winsock: %s\n", getErrorMsg(startupResult)); failed = true; } return !failed; } /* Name: deinitWinsock * Desription: Deinitialized Winsock subsystem * Parameters: none * Return code: none */ void deinitWinsock(void) { WSACleanup(); } /* Name: createTcpSocket * Description: Creates a new, unconnected TCP socket * Parameters: sock - buffer to receive socket * Return code: true if successful * false if an error occurred */ bool createTcpSocket(SOCKET *sock) { bool failed = false; *sock = socket(AF_INET, SOCK_STREAM, 0); if (*sock == INVALID_SOCKET) { fprintf(stderr, "Couldn't create socket: %s\n", getErrorMsg(WSAGetLastError())); failed = true; } return !failed; } /* Name: bindTcpSocket * Description: Binds a TCP socket to a specific port on all interfaces * Parameters: sock - socket to bind * port - port to bind socket to * Return code: true if successful * false if an error occurred */ bool bindTcpSocket(SOCKET sock, unsigned short port) { bool result = false; struct sockaddr_in saddr; saddr.sin_family = AF_INET; saddr.sin_port = htons(port); saddr.sin_addr.s_addr = INADDR_ANY; printf("Binding to %s:%u...", inet_ntoa(saddr.sin_addr), port); fflush(stdout); if (bind(sock, (struct sockaddr*) &saddr, sizeof(saddr)) == 0) { printf(" OK.\n"); result = true; } else { printf(" FAILED.\n"); fprintf(stderr, "Couldn't bind socket: %s\n", getErrorMsg(WSAGetLastError())); } return result; } /* Name: setSocketToListenMode * Description: Sets a bound TCP socket to listen mode * Parameters: sock - socket to set to listen mode * Return code: true if successful * false if an error occurred */ bool setSocketToListenMode(SOCKET sock) { bool failed = false; if (listen(sock, 3) == SOCKET_ERROR) { fprintf(stderr, "Couldn't set socket to listen mode: %s\n", getErrorMsg(WSAGetLastError())); failed = true; } return !failed; } /* Name: acceptClient * Description: Accepts a new client on a socket in listen mode * Parameters: sock - socket in listen mode * client - buffer for socket of new client * Return code: true if successful * false if an error occurred */ bool acceptClient(SOCKET sock, SOCKET *client) { bool result = false; struct sockaddr_in saddr; int size = sizeof(saddr); *client = accept(sock, (struct sockaddr*) &saddr, &size); if (*client >= 0) { printf("Got a new client from %s:%u.\n", inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); result = true; } else { fprintf(stderr, "Accepting client failed: %s\n", getErrorMsg(WSAGetLastError())); } return result; } /* Name: receiveString * Description: Receives and prints a string from a connected socket * Parameters: sock - socket to read from * Return code: true if successful * false if an error occurred */ bool receiveString(SOCKET sock) { int total = 0; bool done = false; bool failed = false; char buffer[BUFFER_SIZE]; while (!done && !failed) { int bytes = recv(sock, buffer + total, sizeof(buffer) - total - 1, 0); if (bytes > 0) { total += bytes; buffer[total] = '\0'; } else if (bytes == 0) { done = true; } else if (bytes == SOCKET_ERROR) { fprintf(stderr, "Couldn't read from socket: %s\n", getErrorMsg(WSAGetLastError())); failed = true; } } if (!failed) { printf("Received %i bytes: <%s>\n", total, buffer); } return !failed; } /* Name: safeCloseSocket * Description: Checks if a socket is valid, closes it. The socket is * set to an invalid value to avoid double free errors. * Parameters: sock - socket to communicate with * Return code: none */ void safeCloseSocket(SOCKET *sock) { if (*sock != INVALID_SOCKET) { closesocket(*sock); *sock = INVALID_SOCKET; } } int main(void) { bool startupSuccessful = false; bool good = startupSuccessful = initWinsock(); SOCKET sock = INVALID_SOCKET; if (good) good = createTcpSocket(&sock); if (good) good = bindTcpSocket(sock, LISTEN_PORT); if (good) good = setSocketToListenMode(sock); SOCKET client = INVALID_SOCKET; if (good) good = acceptClient(sock, &client); if (good) good = receiveString(client); safeCloseSocket(&client); safeCloseSocket(&sock); if (startupSuccessful) deinitWinsock(); return good ? EXIT_SUCCESS : EXIT_FAILURE; }