// // Chat Server, Unix Version // #include #include #include #include #include #include #include #include #include #include #include using namespace std; static void usage(); int s = (-1); // Socket sockaddr_in myAddr; unsigned short myPort = 1234; const int BUFFER_LEN = 2048; char buffer[BUFFER_LEN]; class Client { public: sockaddr_in addr; Client(const sockaddr_in& a): addr(a) {} int compareTo(const Client& c) const { if (addr.sin_addr.s_addr > c.addr.sin_addr.s_addr) { return 1; } else if (addr.sin_addr.s_addr < c.addr.sin_addr.s_addr) { return (-1); } else { if (addr.sin_port > c.addr.sin_port) { return 1; } else if (addr.sin_port < c.addr.sin_port) { return (-1); } else { return 0; } } } bool operator==(const Client& c) const { return (compareTo(c) == 0); } bool operator!=(const Client& c) const { return (compareTo(c) != 0); } bool operator<(const Client& c) const { return (compareTo(c) < 0); } bool operator<=(const Client& c) const { return (compareTo(c) <= 0); } bool operator>(const Client& c) const { return (compareTo(c) > 0); } bool operator>=(const Client& c) const { return (compareTo(c) >= 0); } }; map clients; void sendToAll(const Client& cli, const char* buffer, int len); void printAddress(const sockaddr_in& addr); int main(int argc, char* argv[]) { if (argc > 1) { // Take a port number from a command line if (!isdigit(argv[1][0])) { usage(); return 0; } myPort = (unsigned short) atoi(argv[1]); } // Create a socket s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) { perror("Could not create a socket"); exit(-1); } // Fill in the address structure containing self address memset(&myAddr, 0, sizeof(struct sockaddr_in)); myAddr.sin_family = AF_INET; myAddr.sin_port = htons(myPort); myAddr.sin_addr.s_addr = htonl(INADDR_ANY); // Bind a socket to the address int res = bind(s, (struct sockaddr*) &myAddr, sizeof(myAddr)); if (res < 0) { perror("Cannot bind a socket"); exit(-1); } while (true) { sockaddr_in clientAddr; socklen_t addLen = sizeof(clientAddr); int res = recvfrom( s, buffer, BUFFER_LEN-4, 0, (sockaddr*) &clientAddr, &addLen ); if (res > 0) { buffer[res] = 0; cout << "Message from "; printAddress(clientAddr); cout << " " << buffer << endl; Client cli(clientAddr); clients[cli] = string(buffer); sendToAll(cli, buffer, res); } if (strncmp(buffer, "terminate!", strlen("terminate!")) == 0) break; } shutdown(s, SHUT_RDWR); close(s); return 0; } static void usage() { printf( "A simple Internet server application.\n" ); } void sendToAll(const Client& cli, const char* buffer, int len) { // cout << "sendToAll: message " << buffer << // " len = " << len << endl; map::const_iterator i = clients.begin(); while (i != clients.end()) { const Client& client = i->first; if (client != cli) { /* cout << " Transmitting message to client "; printAddress(client.addr); cout << endl; */ int res = sendto( s, buffer, len, 0, (sockaddr*) &(client.addr), sizeof(sockaddr_in) ); // cout << " sendto: res = " << res << endl; if (res < 0) { perror("sendto error"); } } ++i; } } void printAddress(const sockaddr_in& addr) { cout << ((int)(ntohl(addr.sin_addr.s_addr) >> 24) & 0xff) << "." << ((int)(ntohl(addr.sin_addr.s_addr) >> 16) & 0xff) << "." << ((int)(ntohl(addr.sin_addr.s_addr) >> 8) & 0xff) << "." << ((int)(ntohl(addr.sin_addr.s_addr) ) & 0xff) << ":" << (int)ntohs(addr.sin_port) << endl; }