FIN RST
server.c
#include <sys/socket.h>
#include <netdb.h>
#include <sys/types.h>
#include <errno.h>
#include <netinet/in.h>
#include <arpa/inet.h>//inet_ntop,没有头文件编译过得去,但是运行出错
#include <stdio.h>
//#include <strings.h>
#include <unistd.h>//fork
#include <sys/wait.h>
int main()
{
int sockfd = socket(AF_INET,SOCK_STREAM,0);
if (sockfd < 0)
{
perror("create socket error");
}
struct sockaddr_in server_sock_addr;
bzero(&server_sock_addr,sizeof(struct sockaddr_in));
server_sock_addr.sin_family = AF_INET;
server_sock_addr.sin_port = htons(12345);
inet_pton(AF_INET,"127.0.0.1",(char *)&server_sock_addr.sin_addr);
int ret = bind(sockfd,(struct sockaddr *) &server_sock_addr,sizeof(server_sock_addr));
if(ret < 0)
perror("bind error");
ret = listen(sockfd,1);
if(ret < 0)
perror("listen error");
struct sockaddr_in client_sock_addr ;
int len;
int client_fd;
client_fd = accept(sockfd,(struct sockaddr *) &client_sock_addr,&len);
if( client_fd < 0)
perror("accpet error");
char content [5];
char msg[100] = "cwd";
while(1)
{
int n = read(client_fd,content,sizeof(content));
if(n == 0)//n == 0表示对方发送了FIN,发生在接受RST之前,若是在接受RST之后,则erron为ECONNRESET,阻塞情况下返回值只有>0和<0,
{
printf("read %d byte\n",n);
int len = write(client_fd,msg,100);//引起对方发送RST
printf("write %d byte ok\n",len);//client已经关闭,但是发送扔能成功,但是发送了字节是100
len = read(client_fd,content,sizeof(content));//读到RST
printf("recv %d byte after recv RST\n",len);
len = write(client_fd,msg,100);//对于接收到RST的进程再次写则收到sigpipe信号,默认行为是终止进程
if(len < 0)
{
perror("read error");
}
break;
}
else
{
content[n] = '\0';
printf("recv content is %s\n",content);
}
}
/*
* getpeername
* getsockname
printf("%d\n",client_fd);
struct sockaddr_in sockaddrtmp;
int length = sizeof(struct sockaddr_in);
ret = getsockname(client_fd,(struct sockaddr *)&sockaddrtmp,&length);
if(ret == -1)
perror("getsockname error");
printf("server port = %d\n",htons(sockaddrtmp.sin_port));//网络字节序
printf("server family = %d\n",sockaddrtmp.sin_family);
char addr[16];
char *ptr;
ptr = inet_ntop(AF_INET,(const void *)&sockaddrtmp.sin_addr,addr,16);//网络字节序
printf("server addr = %s\n",ptr);
//printf("address = %s\n",inet_ntoa(sockaddrtmp.sin_addr));
struct sockaddr_in peer_sock;
length = sizeof(peer_sock);
ret = getpeername(client_fd,(struct sockaddr*)&peer_sock,&length);
if(ret == -1)
perror("getpeername error");
printf("peer port = %d\n",htons(peer_sock.sin_port));//网络字节序
printf("peer family = %d\n",peer_sock.sin_family);
printf("peer address = %s\n",inet_ntop(AF_INET,&peer_sock.sin_addr,addr,16));
*/
return 0;
}
client.c
#include <sys/socket.h>
#include <netdb.h>
#include <sys/types.h>
#include <stdio.h>
//#include <arpa/inet.h>//
int main()
{
int fd = socket(AF_INET,SOCK_STREAM,0);
if(fd < 0)
perror("socket error");
struct sockaddr_in server_sock_addr;
server_sock_addr.sin_family = AF_INET;
server_sock_addr.sin_port = htons(12345);
inet_pton(AF_INET,"127.0.0.1",&server_sock_addr.sin_addr);
/*
int ret = bind(fd, (struct sockaddr*)&server_sock_addr, sizeof(client_sock_addr));
if(ret < 0)
perror("bind error");
*/
int ret = connect(fd,(struct sockaddr*)&server_sock_addr,sizeof(server_sock_addr));
if(ret < 0)
perror("connect error");
else printf("connect ok\n");
/*
* getpeername
* getsockname
struct sockaddr_in peer_sock,client_sock;
int len = sizeof(peer_sock);
ret = getpeername(fd,(struct sockaddr*)&peer_sock,&len);
if(ret == -1)
perror("getpeername error");
char addr[16];
printf("peer port = %d\n",peer_sock.sin_port);
printf("peer family = %d\n",peer_sock.sin_family);
char * result = inet_ntop(AF_INET,&peer_sock.sin_addr,addr,16);
if(result == NULL)
perror("inet_ntop error");
printf("peer address %s\n",result);
len = sizeof(client_sock);
ret=getsockname(fd,(struct sockaddr*)&client_sock,&len);
if(ret == -1)
perror("getsockname error");
printf("client port = %d\n",client_sock.sin_port);
printf("client family = %d\n",client_sock.sin_family);
printf("client address %s\n",inet_ntop(AF_INET,&client_sock.sin_addr,addr,16));
*/
char msg[] = "hellor world";
int n = write(fd,msg,strlen(msg));
printf("send %d byte \n",n);
close(fd);
return 0;
}
FIN 关闭socket fd 则发送一个FIN
RST
SIGPIPE 当一个进程向某个已收到RST的套接字执行写操作时,内核向该进程发送一个SIGPIPE信号,该信号的默认行为是终止进程。
第一次写操作引发RST,第二次写操作引发SIGPIPE