读书人

当TCP缓冲区有底据时断开连接向对端

发布时间: 2013-09-06 10:17:17 作者: rapoo

当TCP缓冲区有数据时断开连接,向对端发送的是RST而不是FIN?
RT。。比如服务端向客户端发送数据后就read套接字,客户端睡眠几秒后(保证服务端的数据已经到缓冲区了)就直接退出,然后服务端的read返回-1,错误信息是 Connection reset by peer。用TCPDUMP观察,发现如果服务端没有发送数据,客户端退出时就发送FIN,否则就发送RST。。请问各位,TCP为什么要这么设计,基于什么考量阿?
[解决办法]
本帖最后由 mymtom 于 2013-08-13 16:09:02 编辑 客户端设置了linger选项,并且将linger时间设置为0


/*-
* vi:set ts=4 sw=4:
*/
#ifndef lint
static const char rcsid[] = "$Id$";
#endif /* not lint */

/**
* @file clnt.c
* @brief
*/

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[])
{
int fd;
int ret;
struct sockaddr_in addr;
struct linger linger;
char buf[] = "2013-08-13 14:29:53";

memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
addr.sin_port = htons(12345);

fd = socket(PF_INET, SOCK_STREAM, 0);

if (argc == 2 && atoi(argv[1]) > 0) {
linger.l_onoff = 1;
linger.l_linger = 0;


setsockopt(fd, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger));
}

ret = connect(fd, (const struct sockaddr *)&addr, sizeof(addr));
sleep(1);
close(fd);

return 0;
}



/*-
* vi:set ts=4 sw=4:
*/
#ifndef lint
static const char rcsid[] = "$Id$";
#endif /* not lint */

/**
* @file serv.c
* @brief
*/

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[])
{
int lisnfd;
int clntfd;
int ret;
struct sockaddr_in addr;
int optval;
char buf[] = "2013-08-13 14:29:53";
ssize_t nrecv;

memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(12345);

lisnfd = socket(PF_INET, SOCK_STREAM, 0);
optval = 1;
setsockopt(lisnfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
ret = bind(lisnfd, (const struct sockaddr *)&addr, sizeof(addr));
listen(lisnfd, 10);

clntfd = accept(lisnfd, NULL, NULL);



send(clntfd, buf, strlen(buf), 0);
errno = 0;
nrecv = recv(clntfd, buf, sizeof(buf) - 1, 0);
if (nrecv < 0)
perror("recv");

close(clntfd);
close(lisnfd);

return 0;
}



运行结果:
fb82:/home/mymtom/tmp/rst$ ./serv &
[2] 5119
fb82:/home/mymtom/tmp/rst$ ./clnt 0
[2] - Done ./serv
fb82:/home/mymtom/tmp/rst$ ./serv &
[2] 5121
fb82:/home/mymtom/tmp/rst$ ./clnt 1
recv: Connection reset by peer
[2] - Done ./serv

读书人网 >UNIXLINUX

热点推荐