int main(void) { int sockfd; /* * this is the container for socket's address that contains * address family, ip address, port */ struct sockaddr serv_addr; char filler[16] = {0}; /* just to dump the handle for the spawned thread - no use */ pthread_t receiver_thread; pthread_cond_init(&console_cv, NULL); pthread_mutex_init(&console_cv_lock, NULL); /* * creates a socket of family Internet sockets (AF_INET) and * of type stream. 0 indicates to system to choose appropriate * protocol (eg: TCP) */ sockfd = socket(AF_INET, SOCK_STREAM, 0); /* * Address represented by struct sockaddr: * first 2 bytes: Address Family, * next 2 bytes: port, * next 2 bytes: ipaddr, * next 8 bytes: zeroes */ /* * htons() and htonl() change endianness to * network order which is the standard for network * communication. */ filler[0] = (unsigned short)AF_INET; filler[2] = (unsigned short)htons(port); filler[4] = (unsigned long)htonl(INADDR_ANY); /* copy data in the filler buffer to the socket address */ memcpy(&serv_addr, filler, sizeof serv_addr); /* binds a socket to an address */ bind(sockfd, &serv_addr, sizeof serv_addr); /* makes connection per the socket address */ connect(sockfd, &serv_addr, sizeof serv_addr); printf("%s\n", "Enter a username (max 20 characters, no spaces):"); fgets(username, sizeof username, stdin); /* fgets also reads the \n from stdin, strip it */ username[strlen(username) - 1] = '\0'; register_username(sockfd); /* spawn a new thread that continuously listens for any msgs from server */ pthread_create(&receiver_thread, NULL, receiver, (void*)&sockfd); /* get our console in action, let the user enter commands */ console(sockfd); return 0; }
int main(void) { int sockfd; /* * struct sockaddr defines a socket address. * A socket address is a combination of address family, * ip address and port. * For IP sockets, we may use struct sockaddr_in which is * just a wrapper around struct sockaddr. * Funtions like bind() etc are only aware of struct sockaddr. */ struct sockaddr_in serv_addr; /* just to dump the handle for the spawned thread - no use */ pthread_t receiver_thread; pthread_cond_init(&console_cv, NULL); pthread_mutex_init(&console_cv_lock, NULL); /* * creates a socket of family Internet sockets (AF_INET) and * of type stream. 0 indicates to system to choose appropriate * protocol (eg: TCP) */ sockfd = socket(AF_INET, SOCK_STREAM, 0); /* * Socket adddress represented by struct sockaddr: * first 2 bytes: Address Family, * next 2 bytes: port, * next 4 bytes: ipaddr, * next 8 bytes: zeroes */ /* * htons() and htonl() change endianness to * network order which is the standard for network * communication. */ serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(port); serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); /* * The above achieves what could be done using the following * on a little endian machine. * This breaks if the structure has padding char filler[16] = {0}; filler[0] = AF_INET & 0xFF; filler[1] = AF_INET >> 8 & 0xFF; filler[2] = htons(port) & 0xFF; filler[3] = htons(port) >> 8 & 0xFF; filler[4] = htonl(INADDR_ANY) & 0xFF; filler[5] = htonl(INADDR_ANY) >> 8 & 0xFF; filler[6] = htonl(INADDR_ANY) >> 16 & 0xFF; filler[7] = htonl(INADDR_ANY) >> 24 & 0xFF; memcpy(&serv_addr, filler, sizeof(serv_addr)); */ /* * Note that we do not bind() our socket to any socket adddress here. * This is because on the client side, you would only use bind() if you want * to use a particular client side port to connect to the server. * When you do not bind(), the kernel will pick a port for you. * Read here how kernel gets you a port: https://idea.popcount.org/2014-04-03-bind-before-connect * There are a few protocols in the Unix world that expect clients to connect from a particular port. * Create a new socket address definition and bind it to socket in such cases: struct sockaddr_in client_addr; client_addr.sin_family = AF_INET; client_addr.sin_port = htons(CLIENT_PORT); client_addr.sin_addr.s_addr = htonl(INADDR_ANY); bind(sockfd, (struct sockaddr*) &client_addr, sizeof client_addr); */ /* makes connection per the socket address */ connect(sockfd, (struct sockaddr*) &serv_addr, sizeof serv_addr); printf("%s\n", "Enter a username (max 20 characters, no spaces):"); fgets(username, sizeof username, stdin); /* fgets also reads the \n from stdin, strip it */ username[strlen(username) - 1] = '\0'; register_username(sockfd); /* spawn a new thread that continuously listens for any msgs from server */ pthread_create(&receiver_thread, NULL, receiver, (void*)&sockfd); /* get our console in action, let the user enter commands */ console(sockfd); return 0; }