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(<); 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
对客户端和服务器代码进行编译
-
客户端
-
服务器端
至少两个客户端查询