网络小计5

1.host 和 ip 转换
char *ip = "www.baidu.com";
int value = inet_addr(ip);
if( value == INADDR_NONE )
{
hostent *phost = gethostbyname(ip);

int i = 0;
while( phost->h_addr_list[i] != NULL ) //注意:不能直接打印 phost->h_addr_list[i].它存储的是网络字节序
{
in_addr addr;
memcpy( &addr, phost->h_addr_list[i], phost->h_length);
char *p = inet_ntoa( addr );
std::cout << p << std::endl;
std::cout << inet_addr( p ) << " " << addr.S_un.S_addr << std::endl; //直接用addr.S_un.S_addr很方便啊,不用再此转换
i++;
}
}


2.RST状态

1.如果listen的tcp收到一个到达的ACK会回应RST
2.如果tcp在SYN_SENT状态收到的应答序号小于初始序号(ISS)或者大于下一个发送序号,会发送RST
3.如果tcp在SYN_RECV状态收到一个不在接收窗口内的tcp段,会发送RST
4.如果一个tcp连接已主动关闭并在2MSL等待期间或者已完全关闭(CLOSED)收到tcp段,也可能会发送RST


3.“当用户disconnect后,如果对应的socket没有任何操作悬挂循环中,那么你是无法得到通知的,直到某个时候程序想起这个socket并进行一个操作后才会得到知该客户已经断开”


4.WSARecv函数还有另外一个作用,如果客户端断开连接了,WSARecv会收到一个0字节的返回,我们可以根据这个释放连接对象。如果客户端直接拔网线,WSARecv是检测不到,这是我们要根据超时来检测。


转引自网络:

 当关闭完成端口时,如果还有未处理的Accepte操作,应该先关闭ListenSocket,然后在IOCP中,处理这些Accept操作(进行资源释放等),切记不要强行终止那些没有处理的Accept操作,否则会造成内存泄漏。


关于closesocket操作:

 The closesocket function will initiate cancellation on the outstanding I/O operations, but that does not mean that an application will receive I/O completion for these I/O operations by the time the closesocket function returns. Thus, an application should not cleanup any resources (WSAOVERLAPPED structures, for example) referenced by the outstanding I/O requests until the I/O requests are indeed completed.

在IOCP模式下,如果调用closesocket时有未决的pending   IO,将导致socket被重置,所以有时会出现数据丢失。正统的解决方式是使用shutdown函数(指定SD_SEND标志),注意这时可能有未完成的发送pengding   IO,所以你应该监测是否该连接的所有是否已完成(也许你要用一个计数器来跟踪这些pending   IO),仅在所有send   pending   IO完成后调用shutdown。

MSDN推荐的优雅关闭socket:

  1. Call WSAAsyncSelect to register for FD_CLOSE notification.
  2. Call shutdown with how=SD_SEND.
  3. When FD_CLOSE received, call recv until zero returned, or SOCKET_ERROR.
  4. Call closesocket.

 FD_CLOSE being posted after all data is read from a socket. An application should check for remaining data upon receipt of FD_CLOSE to avoid any possibility of losing data.


对每个使用AcceptEx接受的连接套结字使用setsockopt设置SO_UPDATE_ACCEPT_CONTEXT选项,这个选项原义是把listen套结字一些属性(包括socket内部接受/发送缓存大小等等)拷贝到新建立的套结字,却可以使后续的shutdown调用成功。

/* SO_UPDATE_ACCEPT_CONTEXT is required for shutdown() to work fine*/

       setsockopt( sockClient,

                            SOL_SOCKET,

                            SO_UPDATE_ACCEPT_CONTEXT,

                            (char*)&m_sockListen,

                            sizeof(m_sockListen) ) ;

如果是调用AcceptEX接收的连接 不设置该选项的话,随后的shutdown调用
将返回失败, WSAGetLastError() returns 10057 -- WSANOTCONN


1.使用OVERLAPPED时,一定要memset(&ovl, 0, sizeof(ovl));
2.list::erase(iter);会调用析构函数

3.使用scopelock时,必须用引用,复制无效!

4.WSABuf的内存分配
5.dwCompletionkey不能分配在栈上
6.用AcceptEx时,对端connect时会收到OP_ACCEPT通知,同时dwBytesTransferred为0,lpOverlapped不为0 

客户端关闭后服务端是无法收到通知的,必须用心跳包
{
 骨头(50635102) 14:45:54 
心跳尽量自己发. 不要使用套接字提供的.
(me)14:46:03 
为什么?
 骨头(50635102) 14:46:33 
你懂细节 才能规避陷阱. 如果你什么都不知道. 还是自己发的好.

交谈中请勿轻信汇款、中奖信息、陌生电话,勿使用外挂软件。
 骨头(50635102)  14:47:33
你想想他的执行权是谁给的.
 葬花淚 分享文件 14:47:49
"需要翻译的.txt" 下载
葬花淚(174189648)  14:47:58
......
发错
顶风作案(158513320)  14:48:07
我也是自己的写
自己写的
 骨头(50635102)  14:48:20
弄一个timer就好.
顶风作案(158513320)  14:48:21
不过我是用定时器搞的
但是也存在问题啊
需要处理链接啊
状态检测啥的
自己考虑的东西比较多
 骨头(50635102)  14:49:19
不懂你说的是什么.
顶风作案(158513320)  14:49:33
你要看看服务器的状态吧
还得遍历客户端列表把
 骨头(50635102)  14:49:46
没有心跳. 这些你也得处理.
顶风作案(158513320)  14:50:06
如果用系统的是不是就不需要了
}

调用AcceptEx后,如果立即接着closesocket, GetXXX会返回TRUE,服务端会收到RECV通知,dwByetsTransferred为0。

,如果间隔一段时间再closesocket,GetXXX会返回FALSE,dwByetsTransferred为0。

1.使用semphore来决定投递AcceptEx要注意的:
开始时WaitXXX来投递,在连接被接收后要ReleaseSemaphore
2.同时,在投递AcceptEx前,先将预准备的socket放在容器当中,在程序出错或结束的时候清空容器,以清理未被接受的socket
3.将SOCKET和BUFFER分开,以便在GetCompletionStatus()时方便处理,这样做还有一个好处是在服务器要主动关闭时
  能轮询所有的socket,逐个shutdown。然后逐个等待一段时间,最后closesocket


本地测试,客户端只连接不发送数据,服务端收到连接后如果投递recv,连接为2500左右,如果不投递recv,连接为1.6W左右

你可能感兴趣的:(网络小计5)