- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我有一个服务器程序通过给定的套接字连接到另一个程序,在某些情况下我需要关闭连接并几乎立即在同一个套接字上重新打开它。总的来说,这是可行的,除了我必须等待整整一分钟才能重置套接字。同时,netstat 表明服务器看到的套接字处于 FIN_WAIT2,而客户端看到的是 CLOSE_WAIT。我已经在使用 SO_REUSEADDR,我认为这会阻止等待,但那并没有起到作用。将 SO_LINGER 设置为零也无济于事。我还能做些什么来解决这个问题?
以下是相关的代码片段:
SetUpSocket()
{
// Set up the socket and listen for a connection from the exelerate client.
// Open a TCP/IP socket.
m_baseSock = socket(PF_INET, SOCK_STREAM, IPPROTO_IP);
if (m_baseSock < 0)
{
return XERROR;
}
// Set the socket options to reuse local addresses.
int flag = 1;
if (setsockopt(m_baseSock, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag)) == -1)
{
return XERROR;
}
// Set the socket options to prevent lingering after closing the socket.
//~ linger li = {1,0};
//~ if (setsockopt(m_baseSock, SOL_SOCKET, SO_LINGER, &li, sizeof(li)) == -1)
//~ {
//~ return XERROR;
//~ }
// Bind the socket to the address of the current host and our given port.
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(m_port);
if (bind(m_baseSock, (struct sockaddr*)&addr, sizeof(addr)) != 0)
{
return XERROR;
}
// Tell the socket to listen for a connection from client.
if (listen(m_baseSock, 4) != 0)
{
return XERROR;
}
return XSUCCESS;
}
ConnectSocket()
{
// Add the socket to a file descriptor set.
fd_set readfds;
FD_ZERO(&readfds);
FD_SET(m_baseSock, &readfds);
// Set timeout to ten seconds. Plenty of time.
struct timeval timeout;
timeout.tv_sec = 10;
timeout.tv_usec = 0;
// Check to see if the socket is ready for reading.
int numReady = select(m_baseSock + 1, &readfds, NULL, NULL, &timeout);
if (numReady > 0)
{
int flags = fcntl(m_baseSock, F_GETFL, 0);
fcntl(m_baseSock, flags | O_NONBLOCK, 1);
// Wait for a connection attempt from the client. Do not block - we shouldn't
// need to since we just selected.
m_connectedSock = accept(m_baseSock, NULL, NULL);
if (m_connectedSock > 0)
{
m_failedSend = false;
m_logout = false;
// Spawn a thread to accept commands from client.
CreateThread(&m_controlThread, ControlThread, (void *)&m_connectedSock);
return XSUCCESS;
}
}
return XERROR;
}
ControlThread(void *arg)
{
// Get the socket from the argument.
socket sock = *((socket*)arg);
while (true)
{
// Add the socket to a file descriptor set.
fd_set readfds;
FD_ZERO(&readfds);
FD_SET(sock, &readfds);
// Set timeout to ten seconds. Plenty of time.
struct timeval timeout;
timeout.tv_sec = 10;
timeout.tv_usec = 0;
// Check if there is any readable data on the socket.
int num_ready = select(sock + 1, &readfds, NULL, NULL, &timeout);
if (num_ready < 0)
{
return NULL;
}
// If there is data, read it.
else if (num_ready > 0)
{
// Check the read buffer.
xuint8 buf[128];
ssize_t size_read = recv(sock, buf, sizeof(buf));
if (size_read > 0)
{
// Get the message out of the buffer.
char msg = *buf;
if (msg == CONNECTED)
{
// Do some things...
}
// If we get the log-out message, log out.
else if (msg == LOGOUT)
{
return NULL;
}
}
}
} // while
return NULL;
}
~Server()
{
// Close the sockets.
if (m_baseSock != SOCKET_ERROR)
{
close(m_baseSock);
m_baseSock = SOCKET_ERROR;
}
if (m_connectedSock != SOCKET_ERROR)
{
close(m_connectedSock);
m_connectedSock = SOCKET_ERROR;
}
}
SOCKET_ERROR 等于 -1。服务器对象被销毁,此时连接应该关闭,然后重新创建,此时调用 SetUpSocket() 和 ConnectSocket() 例程。
那么为什么我必须等待一分钟才能清除套接字?任何想法都会受到赞赏。
编辑:按照我的第一张海报的建议,我找到了一种让客户端从其末端关闭套接字的方法。不过还是有些不对劲。现在,netstat 从服务器的角度在 TIME_WAIT 中显示套接字,而从客户端的角度来看没有任何条目。我所拥有的是:
tcp 0 0 localhost.localdomain:19876 localhost.localdomain:54598 TIME_WAIT
反之亦然。服务器和客户端仍然需要一分钟时间来清除 TIME_WAIT 以便能够重新连接。现在出了什么问题 - 在客户端的套接字上使用 close() 是不是不正确?
编辑 2:现在,如果我强制客户端重新连接,它会立即 - 但如果我只是让它做自己的事情,它会等待整整一分钟以清除 TIME_WAIT。我怀疑客户端代码中有问题。我对此无能为力。
最佳答案
服务器正在等待客户端发送一个FIN
数据包。这应该通过关闭客户端的套接字(或者可能关闭应用程序)来完成。然后服务器进入TIME_WAIT
状态,等待socket超时。 SO_REUSEADDR
使您能够绕过此状态。
(来源 http://upload.wikimedia.org/wikipedia/commons/0/08/TCP_state_diagram.jpg)
关于c++ - 关闭套接字时防止 FIN_WAIT2,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5328155/
我正在使用的网站上有一个非 Canvas 导航。关闭 Canvas 导航的默认状态是关闭的,这在移动网站上运行良好,因为您可以打开它并选择您的链接,但在桌面上关闭它并打开它会隐藏用户的信息,我希望它是
我有一个 NSViewController 是这样连接的: 在底部 viewController 中,我尝试使用 self.dismiss(self) 关闭它,但是,它会产生此错误: [General
我昨天制作了一个扩展的 JQuery 搜索框,它的作用就像一个魅力!但是,我在创建一个脚本时遇到问题,当用户单击搜索框时,它会关闭。 这是我的 JQuery: function expandSearc
我一辈子都无法在 API V3 中一次只显示一个信息窗口。我需要一个在下一次开放之前关闭。还希望在 map 上的任何地方关闭 infoWindow onclick。这是否在初始化函数中? 这是我的完整
关闭和清理套接字的正确方法是什么? 我在辅助线程中运行 io_service,我需要关闭与主线程的连接: void closeConnection() { ioc.post([&socket]
我的 Selenium 测试看起来像这样:客户选择金融产品,填写一些必要的数据,并在打印预览中显示条款/协议(protocol)文档(根据本地法律的要求)。打印/关闭打印预览对话框后,客户输入更多数据
我目前正在从 android 网站了解 Navigation Drawer,我正在使用他们的示例 http://developer.android.com/training/implementing-
尝试通过 expo 在模拟器上运行 react-native 应用程序时出现此错误。 Couldn't start project on Android: Error running adb: adb
方法一 function transform(ar) { var alStr = []; for(var i=0; i
我想按以下方式自定义我的抽屉导航: 我希望在抽屉打开时显示一个图标,在抽屉关闭时显示另一个图标,而不是将菜单图标稍微向左滑动的当前默认动画。 关于我在哪里可以找到类似内容的任何想法/线索? 我做了一些
我们刚刚从 0.6.2 或 0.7 升级了我们的 dropwizard 版本,发现 .yml 文件中的很多配置都发生了变化。尽管我们能够弄清楚其中的大部分,但我们无法弄清楚如何关闭“requestLo
从 celery 2.4.5 升级后,我开始让 celery 随机关闭。 我在 centOS 机器上使用 celery 3.0.12、boto 2.6 和 amazon sqs 和 django 1.
我试图包含一些语句来指导用户更多地了解文件无法打开或关闭的原因。文件在写入模式下无法打开的一些可能情况是什么?无法关闭怎么办? FILE *fp; if(!(fp = fopen("testing",
我有一个DLL,可以访问数据库并从存储在配置文件中的应用程序设置中读取连接字符串。然后,引用此DLL的应用程序将需要在其配置文件中为此配置设置设置值。 我遇到的问题是,生成的配置代码会通过Defaul
我将 UIDatePicker 添加为 UITextField 的输入 View UIDatePicker *oBirth; NSDateFormatter *dateFormat; _edit
我有以下代码: SecondViewController *secondView = [[SecondViewController alloc] initWithNibName:@"SecondVie
Closed. This question does not meet Stack Overflow guidelines。它当前不接受答案。 想改善这个问题吗?更新问题,以便将其作为on-topic
通常,按下 option 键关闭窗口会关闭应用程序中的所有窗口。在我的应用程序中,我希望它仅关闭与用户正在关闭的窗口相关的窗口。我怎样才能做到这一点?我可以为所有窗口实现 windowShouldCl
我有一个 NSWindow,它托管一个已连接到脚本处理程序的 WebView。 现在,当用户单击 WebView 上的控件上的按钮时,它会调用我的对象上的 Objective C 方法。 在这种特定情
我想根据 MBP 上的相机使用情况自动化个人工作流程。 基本上我想知道是否任何 的摄像头(内置或 USB)已打开或关闭,因此我可以运行我将创建的程序或脚本。 我认为如果我需要轮询相机状态也可以,但基于
我是一名优秀的程序员,十分优秀!