⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pppserv.c

📁 A peer-to-peer file sharing system under UNIX environment.
💻 C
字号:
#include <stdio.h>#include <sys/socket.h>#include <netinet/in.h>#include <netdb.h>#include <arpa/inet.h>#include <errno.h>#define RIO_BUFSIZE 8192#define LISTENQ 1024#define MAXLINE 8192#define FALSE 0#define TRUE 1#define DATABASE 200typedef struct sockaddr SA;typedef struct {    int rio_fd;                /* descriptor for this internal buf */    int rio_cnt;               /* unread bytes in internal buf */    char *rio_bufptr;          /* next unread byte in internal buf */    char rio_buf[RIO_BUFSIZE]; /* internal buffer */} rio_t;/*  * The in-memory database which stores  * all the file entry information  */typedef struct {    char *title;    char *host_name;    int port;    int valid;} file_entry;/* do the register request from client */int register_file(int connfd, rio_t* riop);/* do the add file request from client */int add_file(int connfd, rio_t* rio);/* do the deregister request from client */int deregister_file(int connfd, rio_t* riop);/* check the file entry in the in-memory database */int check_in_database(char *title, char* host, int port);/* do the query request from client */void query(int connfd, rio_t* riop);/* increment the entry index */void incre(int entry);/* Print the in-memory database (debug) */void print_database();/* The Rio package - robust I/O functions */ssize_t rio_readn(int fd, void *usrbuf, size_t n);ssize_t rio_writen(int fd, void *usrbuf, size_t n);void rio_readinitb(rio_t *rp, int fd); ssize_t	rio_readnb(rio_t *rp, void *usrbuf, size_t n);ssize_t	rio_readlineb(rio_t *rp, void *usrbuf, size_t maxlen);/* The in-memory database */file_entry database[DATABASE];/* The available database entry */int ava_entry = 0;int main(int argc, char **argv){    int port, listenfd, clientlen, connfd;    struct sockaddr_in clientaddr;    int i;        if (argc != 2 )    {        printf("usage: %s <port>\n", argv[0]);	    exit(1);    }    // Clean the database    for (i = 0; i < DATABASE; i++)    {        database[i].valid = FALSE;    }    port = atoi(argv[1]);    listenfd = open_listenfd(port);        while(1)    {        clientlen = sizeof(clientaddr);        connfd = accept(listenfd, (SA *)&clientaddr, &clientlen);                printf("Server connected to a client.\n");            size_t n;         char buf[MAXLINE];         rio_t rio;        rio_readinitb(&rio, connfd);        while((n = rio_readlineb(&rio, buf, MAXLINE)) != 0) {            rio_writen(connfd, buf, n);            if (strcmp(buf, "REGISTER\n") == 0)            {                register_file(connfd, &rio);                break;            }            else if((strcmp(buf, "ADD ENTRY\n") == 0))            {                add_file(connfd, &rio);                               break;            }            else if((strcmp(buf, "DEREGISTER\n") == 0))            {                deregister_file(connfd, &rio);                              break;            }            else if((strcmp(buf, "QUERY\n") == 0))            {                // Fork the child to do the query                if (fork() == 0)                {                    close(listenfd);                    query(connfd,&rio);                    close(connfd);                    exit(0);                }                break;            }                    }        printf("Server closes the current connection.\n");        printf("Server is waiting for the next connection.\n");	    close(connfd);    }    exit(0);    }/* * Register the file entries sent by client. */int register_file(int connfd, rio_t* riop){    size_t n;     char buf[MAXLINE];     char* token, *token1;    int i;    while((n = rio_readlineb(riop, buf, MAXLINE)) != 0) {        if (strcmp(buf, ".\n") == 0)         {            rio_writen(connfd, "SUCCESS\n", 8);            rio_readlineb(riop, buf, MAXLINE);            fflush(stdout);            break;                              }        token = strchr(buf, ':');        token[0] = '\0';                token++;        token1 = strchr(token, ':');        token1[0] = '\0';                token1++;        token1[strlen(token1)-1] = '\0';        // The same entry is in the database alreaedy.        if (check_in_database(buf, token, atoi(token1)))        {            rio_writen(connfd,"in database\n",12);            continue;        }                i = 0;        while(buf[i])        {            buf[i] = tolower(buf[i]);            i++;        }             // Store the entry to the in-memory database                database[ava_entry].title = (char *)malloc(strlen(buf)+1);        strcpy(database[ava_entry].title, buf);        database[ava_entry].host_name = (char *)malloc(strlen(token)+1);        strcpy(database[ava_entry].host_name, token);        database[ava_entry].port = atoi(token1);        database[ava_entry].valid = TRUE;                incre(ava_entry);        rio_writen(connfd,"added\n",6);    }    return TRUE;}/* * Add the file entry to the database. */int add_file(int connfd, rio_t* riop){    size_t n;     char buf[MAXLINE];     char *token, *token1;    while((n = rio_readlineb(riop, buf, MAXLINE)) != 0) {        if (strcmp(buf, ".\n") == 0)         {            rio_writen(connfd, "SUCCESS\n", 8);            rio_readlineb(riop, buf, MAXLINE);            break;                              }        token = strchr(buf, ':');        token[0] = '\0';                token++;        token1 = strchr(token, ':');        token1[0] = '\0';                token1++;        token1[strlen(token1)-1] = '\0';        if (check_in_database(buf, token,atoi(token1)))        {            rio_writen(connfd,"in database\n",12);            continue;        }                database[ava_entry].title = (char *)malloc(strlen(buf)+1);        strcpy(database[ava_entry].title, buf);        database[ava_entry].host_name = (char *)malloc(strlen(token)+1);        strcpy(database[ava_entry].host_name, token);        database[ava_entry].port = atoi(token1);        database[ava_entry].valid = TRUE;                incre(ava_entry);        rio_writen(connfd, "added\n", 6);    }    return TRUE;}/* * Deregister the exit client */int deregister_file(int connfd, rio_t* riop){    size_t n;     char buf[MAXLINE];     char* token, *token1;    int port,i;    while((n = rio_readlineb(riop, buf, MAXLINE)) != 0) {        if (strcmp(buf, ".\n") == 0)         {            rio_writen(connfd, "SUCCESS\n", 8);            rio_readlineb(riop, buf, MAXLINE);            fflush(stdout);            break;                              }        token = strchr(buf, ' ');        token[0] = '\0';                token++;        token[strlen(token)-1] = '\0';        port = atoi(token);        for(i = 0; i < DATABASE; i++)        {            if (database[i].valid             && !strcmp(database[i].host_name, buf)            && (database[i].port == port))            {                database[i].valid = FALSE;            }        }        for(i = 0; i < DATABASE; i++)        {            if (!database[i].valid)                break;        }        ava_entry = i;        rio_writen(connfd,"doing\n",6);    }    return TRUE;}/* * Check the file entry whether in the database */int check_in_database(char *title, char* host, int port){    int i;    for(i = 0; i < DATABASE; i++)    {        if (database[i].valid             && !strcmp(database[i].title,title)            && !strcmp(database[i].host_name, host)            && (database[i].port == port))        {            return TRUE;        }    }    return FALSE;    }/* * Print the database */void print_database(){    int i;    for(i = 0; i < DATABASE; i++)    {        if (database[i].valid)        {            printf("%s %s:%d \n",                 database[i].title, database[i].host_name, database[i].port);        }    }}/* * Increase the database list entry. * ava_entry points to the smallest available entry. */void incre(int entry){    while(database[entry].valid && entry < DATABASE)        entry++;    if (entry == DATABASE)    {        printf("The file database is full!");        ava_entry = -1;    }    ava_entry = entry;}/* * Do the file query . */void query(int connfd, rio_t* riop){    size_t n;     char buf[MAXLINE];     char *x;    char *y;    char *savept;    char *portstr;    int i;    int find = FALSE;    if ((n = rio_readlineb(riop, buf, MAXLINE)) != 0)     {        x = (char *)malloc(strlen(buf)+1);        strcpy(x,buf);        while((y=(char *)strtok_r(x," \t\r\n",&savept))!=NULL)        {            x = savept;                       i = 0;            while(y[i])            {                y[i] = tolower(y[i]);                i++;            }            for(i = 0; i < DATABASE; i++)            {                if (database[i].valid)                {                    if (strstr(database[i].title, y))                    {                         rio_writen(connfd, database[i].title, strlen(database[i].title));                         rio_writen(connfd, ":", 1);                         rio_writen(connfd, database[i].host_name, strlen(database[i].host_name));                         portstr = (char *)malloc(7);                         sprintf(portstr, ":%d", database[i].port);                             rio_writen(connfd, portstr,strlen(portstr));                         rio_writen(connfd, "\n", 1);                         find = TRUE;                    }                }            }                      }        if (find)        {            rio_writen(connfd, "SUCCESS\n", 9);        }        else        {            rio_writen(connfd, "FAILED\n", 7);        }            }}/* * Listen for clients. */ int open_listenfd(int port){    int listenfd, optval = 1;    struct sockaddr_in serveraddr;    if((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)        return -1;        if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR,        (const void *)&optval, sizeof(int)) < 0)	return -1;        bzero((char *)&serveraddr, sizeof(serveraddr));    serveraddr.sin_family = AF_INET;    serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);    serveraddr.sin_port = htons((unsigned short)port);    if(bind(listenfd, (SA *)&serveraddr, sizeof(serveraddr)) < 0)        return -1;    if(listen(listenfd, LISTENQ) < 0)        return -1;    return listenfd;}/* The Rio package - robust I/O functions *//* * rio_readn - robustly read n bytes (unbuffered) */ssize_t rio_readn(int fd, void *usrbuf, size_t n) {    size_t nleft = n;    ssize_t nread;    char *bufp = usrbuf;    while (nleft > 0) {	if ((nread = read(fd, bufp, nleft)) < 0) {	    if (errno == EINTR) /* interrupted by sig handler return */		nread = 0;      /* and call read() again */	    else		return -1;      /* errno set by read() */ 	} 	else if (nread == 0)	    break;              /* EOF */	nleft -= nread;	bufp += nread;    }    return (n - nleft);         /* return >= 0 */}/* * rio_writen - robustly write n bytes (unbuffered) */ssize_t rio_writen(int fd, void *usrbuf, size_t n) {    size_t nleft = n;    ssize_t nwritten;    char *bufp = usrbuf;    while (nleft > 0) {	if ((nwritten = write(fd, bufp, nleft)) <= 0) {	    if (errno == EINTR)  /* interrupted by sig handler return */		nwritten = 0;    /* and call write() again */	    else		return -1;       /* errorno set by write() */	}	nleft -= nwritten;	bufp += nwritten;    }    return n;}/*  * rio_read - This is a wrapper for the Unix read() function. */static ssize_t rio_read(rio_t *rp, char *usrbuf, size_t n){    int cnt;    while (rp->rio_cnt <= 0) {  /* refill if buf is empty */	rp->rio_cnt = read(rp->rio_fd, rp->rio_buf, 			   sizeof(rp->rio_buf));	if (rp->rio_cnt < 0) {	    if (errno != EINTR) /* interrupted by sig handler return */		return -1;	}	else if (rp->rio_cnt == 0)  /* EOF */	    return 0;	else 	    rp->rio_bufptr = rp->rio_buf; /* reset buffer ptr */    }    /* Copy min(n, rp->rio_cnt) bytes from internal buf to user buf */    cnt = n;              if (rp->rio_cnt < n)   	cnt = rp->rio_cnt;    memcpy(usrbuf, rp->rio_bufptr, cnt);    rp->rio_bufptr += cnt;    rp->rio_cnt -= cnt;    return cnt;}/* * rio_readinitb - Associate a descriptor with a read buffer and reset buffer */void rio_readinitb(rio_t *rp, int fd) {    rp->rio_fd = fd;      rp->rio_cnt = 0;      rp->rio_bufptr = rp->rio_buf;}/* * rio_readnb - Robustly read n bytes (buffered) */ssize_t rio_readnb(rio_t *rp, void *usrbuf, size_t n) {    size_t nleft = n;    ssize_t nread;    char *bufp = usrbuf;        while (nleft > 0) {	if ((nread = rio_read(rp, bufp, nleft)) < 0) {	    if (errno == EINTR) /* interrupted by sig handler return */		nread = 0;      /* call read() again */	    else		return -1;      /* errno set by read() */ 	} 	else if (nread == 0)	    break;              /* EOF */	nleft -= nread;	bufp += nread;    }    return (n - nleft);         /* return >= 0 */}/*  * rio_readlineb - robustly read a text line (buffered) */ssize_t rio_readlineb(rio_t *rp, void *usrbuf, size_t maxlen) {    int n, rc;    char c, *bufp = usrbuf;    for (n = 1; n < maxlen; n++) { 	if ((rc = rio_read(rp, &c, 1)) == 1) {	    *bufp++ = c;	    if (c == '\n')		break;	} else if (rc == 0) {	    if (n == 1)		return 0; /* EOF, no data read */	    else		break;    /* EOF, some data was read */	} else	    return -1;	  /* error */    }    *bufp = 0;    return n;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -