socket测试-3(必做)

任务详情:

基于socket 实现daytime(13)服务器(端口我们使用13+后三位学号)和客户端
服务器响应消息格式是

客户端IP:XXXX
服务器实现者学号:XXXXXXXX
当前时间: XX:XX:XX

上方提交代码
提交一个客户端至少查询三次时间的截图测试截图
提交至少两个客户端查询时间的截图测试截图

实践过程

代码

展开查看csapp.c

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

define MAXLINE 100

typedef struct sockaddr SA;

define LISTENQ 1024

define EINTR 4

define RIO_BUFSIZE 8192

typedef struct{

int rio_fd;
int rio_cnt;
char *rio_bufptr;
char rio_buf[RIO_BUFSIZE];

}rio_t;

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;

}

int open_clientfd(char *hostname,int port){

int clientfd;
struct hostent *hp;
struct sockaddr_in serveraddr;

if((clientfd = socket(AF_INET,SOCK_STREAM,0))<0)
    return -1;

if((hp = gethostbyname(hostname))==NULL)
    return -2;

bzero((char *)&serveraddr,sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
bcopy((char *)hp->h_addr_list[0],
        (char *)&serveraddr.sin_addr.s_addr,hp->h_length);
serveraddr.sin_port = htons(port);

if(connect(clientfd,(SA *)&serveraddr,sizeof(serveraddr))<0)
    return -1;

return clientfd;

}

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((nwritten = write(fd,bufp,nleft))<=0){
        
            if(errno == EINTR)
                nwritten = 0;
            else
                return -1;
        }
        nleft -= nwritten;
        bufp += nwritten;
        }
    }
return n;

}

void rio_readinitb(rio_t *rp,int fd){

rp->rio_fd = fd;
rp->rio_cnt = 0;
rp->rio_bufptr = rp->rio_buf;

}

ssize_t rio_read(rio_t *rp,char *usrbuf,size_t n){

int cnt;

while(rp->rio_cnt <=0){

    rp->rio_cnt = read(rp->rio_fd,rp->rio_buf,sizeof(rp->rio_buf));

    if(rp->rio_cnt<0){
    
        if(errno!=EINTR)
            return -1;
    }
    else if(rp->rio_cnt==0)
        return 0;
    else 
        rp->rio_bufptr = rp->rio_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;

}

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;
        else
            break;
    }else
        return -1;
    }

*bufp = 0;
return n;
}

void echo(int connfd){

size_t n;
char buf[MAXLINE];
rio_t rio;

rio_readinitb(&rio,connfd);
while((n = rio_readlineb(&rio,buf,MAXLINE))!=0){
    
    printf("server received %d bytes\n",n);
    
    rio_writen(connfd,buf,n);
}

}

展开查看服务器端代码

#include 
#include 
#include                                                                    
#include 
#include     
#include 
#include 
#include 
#include 
#include 
#include 

define MAXLINE 200

define RIO_BUFSIZE 8192

typedef struct{
int rio_fd;
int rio_cnt;
char *rio_bufptr;
char rio_buf[RIO_BUFSIZE];

}rio_t;

typedef struct sockaddr SA;

typedef struct{
int tm_sec;
int tm_min;
int tm_hour;
int tm_mday;
int tm_mon;
int tm_year;
int tm_wday;
int tm_yday;
int tm_isdst;
}tm;

void sigchld_handler(int sig){

    pid_t pid;
    int stat;

    while((pid = waitpid(-1,&stat,WNOHANG))>0){
        printf("child %d terminated\n",pid);
			        }
    return;

}

int main(int argc,char **argv){

    int listenfd,connfd,port,clientlen;
    struct sockaddr_in clientaddr;
    struct hostent *hp;
    char *haddrp;
    char sbuf[MAXLINE];
    char rbuf[MAXLINE];
    rio_t rio;
    time_t lt;
    tm *local;
    char str1[MAXLINE]="客户端IP:";
    char str2[MAXLINE]="服务器实现者学号:";
    char str3[MAXLINE]="当地时间:";

if(argc != 2){
						        
        fprintf(stderr,"usage:%s <port>\n",argv[0]);
        exit(0);
							        }
  port = atoi(argv[1]);
signal(SIGCHLD,sigchld_handler);
listenfd = open_listenfd(port);
								    while(1){
							        
 clientlen = sizeof(clientaddr);
 connfd = accept(listenfd,(SA *)&clientaddr,&clientlen);
 hp = gethostbyaddr((const char*)&clientaddr.sin_addr.s_addr,
 sizeof(clientaddr.sin_addr.s_addr),AF_INET);
 haddrp = inet_ntoa(clientaddr.sin_addr);
 printf("server connected to %s (%s)\n",hp->h_name,haddrp);
 if(fork() == 0){
 close(listenfd);
 lt = time(NULL); 
 local = localtime(&lt);
 strftime(sbuf,64,"%Y-%m-%d %H:%M:%S",local);
 send(connfd,sbuf,MAXLINE,0);
 close(connfd);
 exit(0);
    }
close(connfd);
																        }

}

展开查看客户端代码

#include 
#include                                                                    
#include 
#include     
#include 
#include 
#include 
#include 

define RIO_BUFSIZE 8192

typedef struct{
int rio_fd;
int rio_cnt;
char *rio_bufptr;
char rio_buf[RIO_BUFSIZE];

}rio_t;

define MAXLINE 200

int main(int argc,char **argv){

int clientfd,port;
char *host,buf[MAXLINE];
char sbuf[MAXLINE];
char rbuf[MAXLINE];
rio_t rio;
char str1[MAXLINE]="客户端IP:";
char str2[MAXLINE]="服务器实现者学号:20191329";

char str3[MAXLINE]="当地时间:";

if(argc!=3){

    fprintf(stderr,"usage:%s <host> <port>\n",argv[0]);
    exit(0);
}
host = argv[1];
port = atoi(argv[2]);

clientfd = open_clientfd(host,port);

while(1){
    

    recv(clientfd,rbuf,MAXLINE,0);

    printf("%s",str1);
    puts(host);

    printf("%s",str2);
    putchar('\n');

    printf("%s",str3);
  
    puts(rbuf);
   
    close(clientfd);
   
    exit(0);
}

}

一个客户端查询多次

使用gcc csapp.c filename.c -o name对客户端和服务器代码进行编译

  • 客户端

  • 服务器端

至少两个客户端查询


posted @ 2021-12-20 11:44  修勾  阅读(49)  评论(0编辑  收藏  举报