/* * A small utility for socket programming * * Modifed from Beej socket programming tutorial * by Hoang Nguyen * * Feel free to modify and copy the code * and use it AT YOUR OWN RISK */ #ifndef MSG_H #define MSG_H #define MAX_MSG_SIZE 512 #define BACKLOG 10 typedef struct{ char data[MAX_MSG_SIZE]; int len; } msg_t; // get sockaddr, IPv4 or IPv6: void *get_in_addr(struct sockaddr *sa) { if (sa->sa_family == AF_INET) { return &(((struct sockaddr_in*)sa)->sin_addr); } return &(((struct sockaddr_in6*)sa)->sin6_addr); } void sendMessage(int sockfd, const msg_t* msg) { send(sockfd, msg->data, msg->len, 0); } void recvMessage(int sockfd, msg_t* msg) { msg->len = recv(sockfd, msg->data, MAX_MSG_SIZE - 1, 0); } void sendRequest(int sockfd, const msg_t* request, msg_t* reply) { sendMessage(sockfd, request); recvMessage(sockfd, reply); } int connectToServer(char* serverName, char* port) { struct addrinfo hints, *serverinfo, *p; int ret; int sockfd; char s[INET6_ADDRSTRLEN]; int numbytes; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; // get the information ret = getaddrinfo(serverName, port, &hints, &serverinfo); if (ret != 0) { printf("\tgetaddrinfo error: %s\n", gai_strerror(ret)); return -1; } for (p = serverinfo; p != NULL; p = p->ai_next) { sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol); if (sockfd == -1) { perror("client: socket"); continue; } if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) { perror("client: socket"); close(sockfd); continue; } break; } if (p == NULL) { printf("cannot connect to the server\n"); return -1; } freeaddrinfo(serverinfo); inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr), s, sizeof(s)); printf("\tConnected to %s:%s\n", s, port); return sockfd; } void startServer(char* port, void *(*servefunc)(int) ) { int sockfd, newfd; int yes = 1; struct addrinfo hints, *serverinfo, *p; struct sockaddr_storage their_addr; // connector's address information char s[INET6_ADDRSTRLEN]; socklen_t sin_size; int ret; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; ret = getaddrinfo(NULL, port, &hints, &serverinfo); if (ret == -1) { printf("\t getaddrinfo: %s\n", gai_strerror(ret)); return; } for (p = serverinfo; p != NULL; p = p->ai_next) { sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol); if (sockfd == -1) { perror("server: socket"); continue; } if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) { perror("setsockopt"); return; } if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) { perror("sever: bind"); close(sockfd); continue; } break; } if (p == NULL) { printf("cannot bind \n"); return; } printf("\t Binded to port %s\n", port); freeaddrinfo(serverinfo); if (listen(sockfd, BACKLOG) == -1) { perror("listen"); return; } printf("Waiting for incoming connections...\n"); while (1) { sin_size = sizeof(their_addr); newfd = accept(sockfd, (struct sockaddr *) &their_addr, &sin_size); if (newfd == -1) { perror("accept"); continue; } inet_ntop(their_addr.ss_family, get_in_addr( (struct sockaddr *) &their_addr), s, sizeof(s)); printf("\tGot connection from %s\n", s); servefunc(newfd); } } #endif