/* Project 3 testing server code for use with CSE 461 project 3: * http://www.cs.washington.edu/education/courses/cse461/CurrentQtr/projects/proj3.html * * v1.0 */ #include #include #include #include #include #include #include #include #include #include #include #include #define SERVER_PORT 8083 #define CLIENT_TIMEOUT 5 #define TIMEOUT 0 #define SUCCESS 1 #define FAILURE 2 #define DISCONNECTED 3 typedef struct msg { uint32_t len; void* payload; } msg_t; int wait_for_msg(int fd, int seconds) { /* wait for the socket to be come readable with a timeout of * seconds */ struct timeval timeout; int rc; fd_set fds; timeout.tv_sec = seconds; timeout.tv_usec = 0; FD_ZERO(&fds); FD_SET(fd, &fds); rc = select(fd+1, &fds, NULL, NULL, &timeout); if (rc < 0) { perror("select failed"); } return rc; } int recv_len(void* buf, int exp_len, int fd) { /* receives exp_len bytes into buf on fd. returns 0 on * timeout, a negative value on error, and 1 on success. buf * must be allocated, fd must be readable, exp_len >= 0 */ int recvd = 0; /* total bytes received */ int rc; while (recvd != exp_len) { /* handle timeout */ if (wait_for_msg(fd,CLIENT_TIMEOUT) <= 0){ printf("timedout waiting for client to send a msg, expected %d bytes, received %d\n",exp_len,recvd); return TIMEOUT; } /* recv into buf */ rc = recv(fd, buf + recvd, exp_len - recvd, 0); if (rc < 0) { perror("failed to recv() on socket"); return FAILURE; } else if (rc == 0) { printf("client closed connection\n"); return DISCONNECTED; } recvd += rc; } return SUCCESS; } int recv_tcp_msg(msg_t** msg_ptr_ptr, int fd) { /* recvd a message on fd, and write it into msg_ptr_ptr, * allocating a new buffer for the message */ int rc; msg_t* msg; msg = calloc(sizeof(msg_t), 1); if (msg == NULL) { perror("calloc"); return FAILURE; } /* 1. receive first 4 bytes indicating length of msg payload */ rc = recv_len(msg, 4, fd); if (rc != SUCCESS) { free(msg); return rc; } /* 2. allocate msg payload buffer */ msg->len = ntohl(msg->len); msg->payload = calloc(msg->len,1); if (msg->payload == NULL) { perror("calloc"); free(msg); return FAILURE; } /* 3. receive msg payload buffer */ rc = recv_len(msg->payload, msg->len, fd); if (rc != SUCCESS) { free(msg->payload); free(msg); return rc; } *msg_ptr_ptr = msg; return SUCCESS; } int main(int argc, char *argv[]) { int tcp_sd; /* listening socket */ int tcp_active_sd; /* accepted socket */ int rc; /* return code */ socklen_t retLen; struct sockaddr_in servAddr, retAddr; msg_t* msg; /* create socket */ tcp_sd=socket(AF_INET, SOCK_STREAM, 0); if(tcp_sd<0) { perror("socket"); printf("cannot open socket \n"); exit(1); } /* bind local server port */ servAddr.sin_family = AF_INET; servAddr.sin_addr.s_addr = htonl(INADDR_ANY); servAddr.sin_port = htons(SERVER_PORT); rc = bind (tcp_sd, (struct sockaddr *) &servAddr,sizeof(servAddr)); if(rc<0) { perror("bind"); printf("cannot bind port number %d \n", SERVER_PORT); close(tcp_sd); exit(1); } /* begin listening on the socket */ if (listen(tcp_sd,1) != 0){ perror("listen"); printf("failed to listen on new TCP sock\n"); exit(1); } printf("waiting for a connection on port %d..\n", SERVER_PORT); /* accept a connection */ retLen = sizeof(retAddr); if ((tcp_active_sd = accept(tcp_sd, (struct sockaddr *) &retAddr, &retLen)) < 0) { perror("accept"); printf("accept failed on new TCP sock\n"); close(tcp_sd); exit(1); } printf("accepted a new connection\n"); /* server infinite loop */ while(1) { printf("waiting for a msg..\n"); /* receive a message */ rc = recv_tcp_msg(&msg, tcp_active_sd); if (rc == SUCCESS){ printf("received msg of length %u, with payload 0x%x\n", msg->len, *(char*)(msg->payload)); free(msg->payload); free(msg); } else if (rc == DISCONNECTED) { break; } } close(tcp_active_sd); close(tcp_sd); return 0; }