day2-错误检测机制及读写操作
在程序编写过程中,我们不希望只看到编译器给我们的错误,在较大的项目中难以定位错误发生的位置,感觉和ICMP协议较为相似用以返回各种错误信息。
服务器/客户端开始读写数据就需要缓存区buffer出现了,计算机网络中很多关于buffer的知识,窗口大小等一系列。
1、错误检测机制
没什么好说的,就是发生生了什么情况,我们会进行一个中断,发送一个消息告诉用户。
void errif(bool condition, const char *errmsg){
if(condition){
perror(errmsg);
exit(EXIT_FAILURE);
}
}
2、服务器
首先罗列一下和之前差别不大的部分,这部分只是增加了错误检测机制
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
errif(sockfd == -1, "socket create error");
struct sockaddr_in serv_addr;
bzero(&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
serv_addr.sin_port = htons(8888);
errif(bind(sockfd, (sockaddr*)&serv_addr, sizeof(serv_addr)) == -1, "socket bind error");
errif(listen(sockfd, SOMAXCONN) == -1, "socket listen error");
struct sockaddr_in clnt_addr;
socklen_t clnt_addr_len = sizeof(clnt_addr);
bzero(&clnt_addr, sizeof(clnt_addr));
int clnt_sockfd = accept(sockfd, (sockaddr*)&clnt_addr, &clnt_addr_len);
errif(clnt_sockfd == -1, "socket accept error");
printf("new client fd %d! IP: %s Port: %d\n", clnt_sockfd, inet_ntoa(clnt_addr.sin_addr), ntohs(clnt_addr.sin_port));
这里开始对缓冲区进行设计,服务器的缓冲区目前只完成读操作,读取数据到缓冲区,再由缓冲区读出做显示,read_bytes这里作为一个用以判断读取状态显示对应信息的操作码。
while (true) {
char buf[1024];
bzero(&buf, sizeof(buf));
ssize_t read_bytes = read(clnt_sockfd, buf, sizeof(buf));
if(read_bytes > 0){
printf("message from client fd %d: %s\n", clnt_sockfd, buf);
write(clnt_sockfd, buf, sizeof(buf));
} else if(read_bytes == 0){
printf("client fd %d disconnected\n", clnt_sockfd);
close(clnt_sockfd);
break;
} else if(read_bytes == -1){
close(clnt_sockfd);
errif(true, "socket read error");
}
}
这里很好对应就不细讲了,但是注意有个点,在成功从客户端读取到数据后需要再将缓存中的数据写入客户端用作回显,验证数据正确性。
3、客户端
同样,将之前相同的代码加上错误检测机制的部分写出来
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
errif(sockfd == -1, "socket create error");
struct sockaddr_in serv_addr;
bzero(&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
serv_addr.sin_port = htons(8888);
errif(connect(sockfd, (sockaddr*)&serv_addr, sizeof(serv_addr)) == -1, "socket connect error");
设计同服务器,区别主要在需要自己向缓冲区写入数据,再通过缓冲区写入客户端,客户端读取
while(true){
char buf[1024];
bzero(&buf, sizeof(buf));
scanf("%s", buf);
ssize_t write_bytes = write(sockfd, buf, sizeof(buf));
if(write_bytes == -1){
printf("socket already disconnected, can't write any more!\n");
break;
}
bzero(&buf, sizeof(buf));
ssize_t read_bytes = read(sockfd, buf, sizeof(buf));
if(read_bytes > 0){
printf("message from server: %s\n", buf);
}else if(read_bytes == 0){
printf("server socket disconnected!\n");
break;
}else if(read_bytes == -1){
close(sockfd);
errif(true, "socket read error");
}
}