下午检查灰度部署的结果,突然系统有点延迟,原来是因为网络策略的变更,导致防火墙把socket的一个主连接挡住了。
虽然会自动切换到备连接,但是系统每隔5分钟会再去检查主连接是否恢复。
这个时候,由于防火墙挡掉的socket链接就会阻塞很长一段时间才会返回错误,需要修改。
因为在Linux下面的情况比较简单,提供一个下面的语句做参考。
setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)); // 通过SO_SNDTIMEO来控制connect的超时时间
据表哥介绍,这个设置原本是用来设置发送超时的,不过Linux下面貌似会很”巧合”的把连接超时也搞定了。
Windows下面当然没这么简单,下面整理网上的一些资料,对windows下面的socket非阻塞链接做探讨。
写在前面:下面的程序在windows下编译需要链接ws2_32.lib/DLL
1. 客户端测试
#include
#include
#include
#include
#include
#define IP_ADDRESS "172.30.7.83"
int PORT = 4000;
WSADATA wsd;
SOCKET cClient;
int ret;
struct sockaddr_in server;
hostent *host=NULL;
int main()
{
if( WSAStartup(MAKEWORD(2,0),&wsd) )
{
return 0;
}
cClient = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if( cClient == INVALID_SOCKET)
{
return 0;
}
//set Recv and Send time out
int TimeOut=6000; //设置发送超时6秒
if(::setsockopt(cClient, SOL_SOCKET, SO_SNDTIMEO, (char *)&TimeOut, sizeof(TimeOut)) == SOCKET_ERROR)
{
return 0;
}
TimeOut=6000;//设置接收超时6秒
if(::setsockopt(cClient, SOL_SOCKET, SO_RCVTIMEO, (char *)&TimeOut, sizeof(TimeOut)) == SOCKET_ERROR)
{
return 0;
}
//设置非阻塞方式连接
unsigned long ul = 1;
ret = ioctlsocket(cClient, FIONBIO, (unsigned long*)&ul);
if (ret == SOCKET_ERROR) return 0;
//连接
server.sin_family = AF_INET;
server.sin_port = htons(PORT);
server.sin_addr.s_addr = inet_addr(IP_ADDRESS);
if(server.sin_addr.s_addr == INADDR_NONE)
{
return 0;
}
connect(cClient,(const struct sockaddr *)&server,sizeof(server));
//select 模型,即设置超时
struct timeval timeout ;
fd_set r;
FD_ZERO(&r);
FD_SET(cClient, &r);
timeout.tv_sec = 3; //连接超时3秒
timeout.tv_usec =0;
printf("start to connect!\n");
ret = select(0, 0, &r, 0, &timeout);
if ( ret <= 0 )
{
::closesocket(cClient);
return 0;
}
char * SendBuffer = "亚瑟王,你找到圣杯了!\n";
ret = send(cClient, SendBuffer, (int)strlen(SendBuffer), 0);
////一般非锁定模式套接比较难控制,可以根据实际情况考虑 再设回阻塞模式
// unsigned long ul1= 0 ;
// ret = ioctlsocket(cClient, FIONBIO, (unsigned long*)&ul1);
// if(ret==SOCKET_ERROR){
// ::closesocket (cClient);
// return 0;
// }
printf("%d\n", ret);
system("pause");
return 0;
}
2. 另外赠送一个Server端:
//Server.cpp
#include
#include
using namespace std;
#define PORT 4000
#define IP_ADDRESS "172.30.7.83"
DWORD WINAPI ClientThread(LPVOID lpParameter)
{
SOCKET CientSocket = (SOCKET)lpParameter;
int Ret = 0;
char RecvBuffer[MAX_PATH];
while ( true )
{
memset(RecvBuffer, 0x00, sizeof(RecvBuffer));
Ret = recv(CientSocket, RecvBuffer, MAX_PATH, 0);
if ( Ret == 0 || Ret == SOCKET_ERROR )
{
cout<<"客户端退出!"<
最后,VIM删除列的方法,V模式,ctrl+V,移动,x or d