- 论坛徽章:
- 0
|
最近在学习《unix网络编程》,在第5章内容中有个例子:在客户与服务器之间传递二进制结构,让人百思不得其解的是为嘛在Readn函数中调用read函数读取数据时,直接返回0?客户端明明已经把数据write进去了,难道是木有flush,导致客户端套接字发送缓冲区中的数据根本木有发送给服务器?代码中省略了头文件包含,代码跟下面是客户端代码:
- #define MAXLINE 4096
- #define SERV_PORT 9875
- #define SA struct sockaddr
- struct args
- {
- long arg1;
- long arg2;
- };
- struct result
- {
- long sum;
- };
- void print_errno()
- {
- printf("stderr:%s\n",strerror(errno));
- }
- void err_quit(const char* err_msg)
- {
- printf("%s",err_msg);
- printf("\n");
- return;
- }
- ssize_t Readn(int fd,void *vptr,size_t n)
- {
- size_t nleft;
- ssize_t nread;
- char* ptr;
- ptr = reinterpret_cast<char*>(vptr);
- nleft = n;
- while(nleft > 0)
- {
- if((nread = read(fd,ptr,nleft) < 0))
- {
- if(errno == EINTR)
- nread = 0;
- else
- return -1;
- }else if(nread == 0)
- break;//EOF
- nleft -= nread;
- ptr += nread;
- }
- return n - nleft;
- }
- ssize_t Writen(int fd,const void *vptr,size_t n)
- {
- size_t nleft;
- ssize_t nwritten;
- const char* ptr;
- ptr = reinterpret_cast<const char*>(vptr);
- nleft = n;
- while(nleft > 0)
- {
- if((nwritten = write(fd,ptr,nleft)) <= 0)
- {
- if(nwritten < 0 && errno == EINTR)
- nwritten = 0;
- else
- {
- print_errno();
- return -1;
- }
- }
- nleft -= nwritten;
- ptr += nwritten;
- }
- return n - nleft;
- }
- void str_cli_new(FILE* fp,int sockfd)
- {
- char sendline[MAXLINE];
- struct args args;
- struct result result;
- while(fgets(sendline,MAXLINE,fp) != NULL)
- {
- if(sscanf(sendline,"%ld%ld",&args.arg1,&args.arg2) != 2)
- {
- printf("invalid input:%s",sendline);
- continue;
- }
- printf("arg1:%ld arg2:%ld\n",args.arg1,args.arg2);
- Writen(sockfd,&args,sizeof(args));
- if(Readn(sockfd,&result,sizeof(result)) == 0)
- err_quit("str_cli:server terminated prematurely");
- printf("%ld\n",result.sum);
- }
- }
- int main(int argc,char** argv)
- {
- int sockfd;
- struct sockaddr_in servaddr;
- if(argc != 2)
- err_quit("usage:tcpcli<IPaddress>");
- sockfd = socket(AF_INET,SOCK_STREAM,0);
- bzero(&servaddr,sizeof(servaddr));
- servaddr.sin_family = AF_INET;
- servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
- servaddr.sin_port = htons(SERV_PORT);
- inet_pton(AF_INET,argv[1],&servaddr.sin_addr);
- signal(SIGPIPE,SIG_IGN);
- int res = connect(sockfd,(SA*)&servaddr,sizeof(servaddr));
- printf("The result of connection is %d\n",res);
- if(res < 0)
- printf("stderr:%s",strerror(errno));
- str_cli_new(stdin,sockfd);
- if(errno == EPIPE)
- printf("Broken pipe\n");
- else
- printf("errno is %d",errno);
- exit(0);
- }
复制代码 服务器代码:- #define MAXLINE 4096
- #define LISTENQ 1024
- #define SERV_PORT 9875
- #define SA struct sockaddr
- typedef void Sigfunc(int);
- void sig_chld(int signo);
- Sigfunc* signal(int signo,Sigfunc* func);
- struct args
- {
- long arg1;
- long arg2;
- };
- struct result
- {
- long sum;
- };
- void err_sys(const char* err_msg)
- {
- printf("%s",err_msg);
- printf("\n");
- exit(0);
- }
- void print_errno()
- {
- printf("stderr:%s\n",strerror(errno));
- }
- ssize_t Readn(int fd,void *vptr,size_t n)
- {
- size_t nleft;
- ssize_t nread;
- char* ptr;
- printf("Readn begin here.\n");
- ptr = reinterpret_cast<char*>(vptr);
- nleft = n;
- while(nleft > 0)
- {
- if((nread = read(fd,ptr,nleft) < 0))
- {
- if(errno == EINTR)
- {
- printf("EINTR error\n");
- nread = 0;
- }
- else
- {
- print_errno();
- printf("error in function Readn\n");
- return -1;
- }
- }else if(nread == 0)
- {
- printf("EOF");
- break;//EOF
- }
- nleft -= nread;
- ptr += nread;
- }
- return n - nleft;
- }
- ssize_t Writen(int fd,const void *vptr,size_t n)
- {
- size_t nleft;
- ssize_t nwritten;
- const char* ptr;
- ptr = reinterpret_cast<const char*>(vptr);
- nleft = n;
- while(nleft > 0)
- {
- if((nwritten = write(fd,ptr,nleft)) <= 0)
- {
- if(nwritten < 0 && errno == EINTR)
- nwritten = 0;
- else
- {
- print_errno();
- return -1;
- }
- }
- nleft -= nwritten;
- ptr += nwritten;
- }
- return n - nleft;
- }
- void str_echo_new(int sockfd)
- {
- ssize_t n;
- struct args args;
- struct result result;
- for(;;)
- {
- if((n = Readn(sockfd,&args,sizeof(args))) == 0)
- {
- return;
- }
- printf("arg1:%ld arg2:%ld\n",args.arg1,args.arg2);
- result.sum = args.arg1 + args.arg2;
- Writen(sockfd,&result,sizeof(result));
- }
- }
- int main()
- {
- int listenfd,connfd;
- pid_t childpid;
- socklen_t clilen;
- struct sockaddr_in cliaddr,servaddr;
- listenfd = socket(AF_INET,SOCK_STREAM,0);
- bzero(&servaddr,sizeof(servaddr));
- servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
- servaddr.sin_port = htons(SERV_PORT);
- int bind_res = bind(listenfd,(SA*)&servaddr,sizeof(servaddr));
- if(bind_res < 0)
- print_errno();
- listen(listenfd,LISTENQ);
- signal(SIGCHLD,sig_chld);
- if(bind_res < 0)
- print_errno();
- for(;;)
- {
- clilen = sizeof(cliaddr);
- if((connfd = accept(listenfd,(SA*)&servaddr,&clilen)) < 0)
- {
- if(errno == EINTR)
- continue;
- else
- err_sys("accept error");
- }
- printf("An connection has been received.\n");
- if((childpid = fork()) == 0)
- {
- close(listenfd);
- str_echo_new(connfd);
- close(connfd);
- exit(0);
- }
- close(connfd);
- }
- }
复制代码 代码跟书中的代码有点儿出入,不过结构基本上一样,启动服务器,然后启动客户端,命令行参数时127.0.0.1,可以发现服务器客户端连接成功,然后在客户端输入两个整数,回车,如果调试的可以发现write操作是成功的,也就是数据至少成功写入了套接字的发送缓冲区。不过服务器这边在fork子进程中,试图调用read操作去读取对应套接字接受缓冲区内容时,返回值为0,难道服务器响应套接字根本没有接收到数据?为什么呢?这个问题困扰小菜几天了,往各位大神不吝赐教哈
|
|