change implement of timeout_recv

This commit is contained in:
ubuntu201711081 2020-12-04 04:39:58 +00:00
parent eca169cd4f
commit 923349635d
5 changed files with 26 additions and 40 deletions

View File

@ -1,9 +1,10 @@
CC = gcc CC = gcc
CFLAGS = -lm -Wall -O2 CFLAGS = -lm -Wall -O2
Bin = server client
all: all:
make client make $(Bin)
make server
socket_wrapper.o: socket_wrapper.c socket_wrapper.h socket_wrapper.o: socket_wrapper.c socket_wrapper.h
$(CC) -c socket_wrapper.c -o socket_wrapper.o $(CFLAGS) $(CC) -c socket_wrapper.c -o socket_wrapper.o $(CFLAGS)
@ -13,5 +14,6 @@ client: socket_wrapper.o client.c
server: server:
$(CC) -o server server.c socket_wrapper.o $(CFLAGS) $(CC) -o server server.c socket_wrapper.o $(CFLAGS)
.PHONY: clean
clean: clean:
rm *.o server client rm *.o $(Bin)

View File

@ -123,7 +123,6 @@ int main(int argc, const char *argv[]){
const char * server_name; const char * server_name;
in_port_t server_port = SERVER_PORT; in_port_t server_port = SERVER_PORT;
int sock; int sock;
register_alarm();
if (argc != 4){ if (argc != 4){
fprintf(stderr,"invaild arguments number."); fprintf(stderr,"invaild arguments number.");
return 1; return 1;

View File

@ -147,7 +147,6 @@ int main(int argc, const char *argv[]){
socklen_t client_addr_len = sizeof(client_addr); socklen_t client_addr_len = sizeof(client_addr);
int csock; int csock;
int bufsize; int bufsize;
register_alarm();
sock = socket(AF_INET,SOCK_STREAM,0); sock = socket(AF_INET,SOCK_STREAM,0);
atexit(safe_exit); atexit(safe_exit);
if(sock < 0){ if(sock < 0){

View File

@ -4,6 +4,8 @@
#include <errno.h> #include <errno.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <poll.h>
#include "socket_wrapper.h" #include "socket_wrapper.h"
int getBufferSizeFrom(int sock){ int getBufferSizeFrom(int sock){
@ -18,39 +20,26 @@ int getBufferSizeFrom(int sock){
return buffer_sz; return buffer_sz;
} }
static uint64_t timer_ticks = 0;
static void alarm_handler(int signum){
timer_ticks++;
}
void register_alarm(){
struct sigaction sigact;
sigact.sa_flags = SA_INTERRUPT;
sigemptyset(&sigact.sa_mask);
sigaddset(&sigact.sa_mask,SIGALRM);
sigact.sa_handler = alarm_handler;
sigaction(SIGALRM, &sigact ,NULL);
}
ssize_t timeout_recv(int fd,void * buf,size_t n,int timeout) ssize_t timeout_recv(int fd,void * buf,size_t n,int timeout)
{ {
ssize_t ret; ssize_t ret;
uint64_t cur = timer_ticks; int poll_ret;
int die_count = 0; struct pollfd fd_single;
for(;;){ fd_single.fd = fd;
alarm(timeout); fd_single.events = POLL_IN;
ret = recv(fd,buf,n,0); poll_ret = (poll(&fd_single,1,timeout * 1000));
if (ret < 0 && errno == EINTR && cur != timer_ticks) if (poll_ret < 0) return -1;
else if(poll_ret == 0) return -2;
switch (fd_single.revents){
case POLLHUP: //We'll treat hangups state like timeouts state.
return -2; return -2;
alarm(0); case POLLERR:
if (ret == 0){ case POLLNVAL:
usleep(100000); return -1;
die_count++; case POLL_IN:
if(die_count > timeout*10){ return recv(fd,buf,n,0);
return -2; default:
} assert(0 && "unreachable");
}
else break;
} }
return ret; return ret;
} }

View File

@ -43,13 +43,10 @@ struct TransferResult{
int getBufferSizeFrom(int sock); int getBufferSizeFrom(int sock);
/*register alarm for timeout_recv()*/
void register_alarm();
/* /*
return -2 if timeout occur. return -2 if timeout occur.
otherwise, implement equal to 'recv'. otherwise, implement equal to 'recv'.
you must call register_alarm() before you use this. `timeout` unit is second.
Since alarm() is called by internal implementation, don't use it if other alarms already exist.
*/ */
ssize_t timeout_recv(int fd,void * buf,size_t n,int timeout); ssize_t timeout_recv(int fd,void * buf,size_t n,int timeout);
/* /*