First enter the code:
//server
void newConnection(int sockfd,const InetAddress &addr)
{
::write(sockfd, "how are you?\n", 13); //简单地回复一句话
}
int main()
{
EventLoop loop;
InetAddress listenAddr(12345);
Acceptor acceptor(&loop, listenAddr);
acceptor.setConnectionCallback(newConnection); //listenfd可读(新连接)调用回调
acceptor.listen(); //Accept::listen调用listenfd的listen
//while(true)循环,Acceptor构造时讲listenfd放进loop的epoll结构中,
//本循环检测到listenfd可读(新连接)之后调用accept得到connfd,然后调用上面set的回调函数
loop.loop();
}
//client
int main(int argc, char **argv)
{
struct sockaddr_in addr;
bzero(&addr, sizeof addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(12345);
inet_pton(AF_INET, argv[1], &addr.sin_addr);
int sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
connect(sockfd, (struct sockaddr *)&addr, sizeof(addr)); //连接server
char buf[256] = {'rrreee'};
read(sockfd, buf, sizeof(buf)); //接受msg
printf("Received: %s\n", buf);
close(sockfd);
return 0;
}
The entire program flow is roughly as follows:
After the server starts, the Acceptor is in the listening state, and then the client requests a connection. If the connection is successful, the server calls the callback newConnection to send "how are you" to the client, and the client prints it out after accepting it.
The error situation is described below:
Using gdb debugging, it is found that every time ::write(sockfd, "how are you?\n", 13);
will receive SIGPIPE
Then the program dies.
After checking Program received signal SIGPIPE, Broken pipe., the reason is said to be writing to invalid (not connected or disconnected) sockfd. But when my program runs to the write of the callback function, the connection does not close. (For debugging, I also commented out the close that appears in all codes)
In addition, when debugging gdb to write, I also used ll /proc/pid/fd
to check the current system occupation descriptor, and connfd still exists.
So I don’t understand why there is SIGPIPE at all, please give me some advice!
我想大声告诉你2017-05-16 13:20:39
Solved, the reason is that the third parameter of ::accept is incorrectly passed
In my code, the accept wrapper is as follows:
Accept(int listenfd, struct sockaddr *addr)
{
socklen_t len = sizeof(*addr);
int connfd = ::accept(listenfd, addr, &len);
//...
}
The calling code is
struct sockaddr_in addr;
//...
int connfd = Accept(listenfd, &addr);
The error should be that the third parameter of ::accpet should be passed the size of the original sockaddr_in instead of the size of the converted sockaddr. Modified as follows:
Accept(int listenfd, struct sockaddr_in *addr)
{
socklen_t len = sizeof(*addr);
int connfd = ::accept(listenfd, (struct sockadr*)addr, &len);
//...
}
Post a man 2 accept
:
The addrlen argument is a value-result argument: the caller must initialize it to contain the size (in bytes) of the structure pointed to by addr; on return it will contain the actual size of the peer address.