TCP/IPWinsock编程要点
2008-04-09 04:08:56来源:互联网 阅读 ()
1、快速通信
Winsock的Nagle算法将降低小数据报的发送速度,而系统默认是使用Nagle算法,使用
int setsockopt(
SOCKET s,
int level,
int optname,
const char FAR *optval,
int optlen
);函数关闭它
例子:
SOCKET sConnect;
sConnect=::socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
int bNodelay = 1;
int err;
err = setsockopt(
sConnect,
IPPROTO_TCP,
TCP_NODELAY,
(char *)&bNodelay,
sizoeof(bNodelay));//不采用延时算法
if (err != NO_ERROR)
TRACE ("setsockopt failed for some reason\n");;
2、SOCKET的SegMentSize和收发缓冲
TCPSegMentSize是发送接受时单个数据报的最大长度,系统默认为1460,收发缓冲大小为8192。
在SOCK_STREAM方式下,如果单次发送数据超过1460,系统将分成多个数据报传送,在对方接受到的将是一个数据流,应用程序需要增加断帧的判断。当然可以采用修改注册表的方式改变1460的大小,但MicrcoSoft认为1460是最佳效率的参数,不建议修改。
在工控系统中,建议关闭Nagle算法,每次发送数据小于1460个字节(推荐1400),这样每次发送的是一个完整的数据报,减少对方对数据流的断帧处理。
3、同步方式中减少断网时connect函数的阻塞时间
同步方式中的断网时connect的阻塞时间为20秒左右,可采用gethostbyaddr事先判断到服务主机的路径是否是通的,或者先ping一下对方主机的IP地址。
A、采用gethostbyaddr阻塞时间不管成功与否为4秒左右。
例子:
LONG lPort=3024;
struct sockaddr_in ServerHostAddr;//服务主机地址
ServerHostAddr.sin_family=AF_INET;
ServerHostAddr.sin_port=::htons(u_short(lPort));
ServerHostAddr.sin_addr.s_addr=::inet_addr("192.168.1.3");
HOSTENT* pResult=gethostbyaddr((const char *) &
(ServerHostAddr.sin_addr.s_addr),4,AF_INET);
if(NULL==pResult)
{
int nErrorCode=WSAGetLastError();
TRACE("gethostbyaddr errorcode=%d",nErrorCode);
}
else
{
TRACE("gethostbyaddr %s\n",pResult->h_name);;
}
B、采用PING方式时间约2秒左右
暂略
采用select函数解决,在收发前先检查读写可用状态。
A、读
例子:
TIMEVAL tv01 = {0, 1};//1ms钟延迟,实际为0-10毫秒
int nSelectRet;
int nErrorCode;
FD_SET fdr = {1, sConnect};
nSelectRet=::select(0, &fdr, NULL, NULL, &tv01);//检查可读状态
if(SOCKET_ERROR==nSelectRet)
{
nErrorCode=WSAGetLastError();
TRACE("select read status errorcode=%d",nErrorCode);
::closesocket(sConnect);
goto 重新连接(客户方),或服务线程退出(服务方);
}
if(nSelectRet==0)//超时发生,无可读数据
{
继续查读状态或向对方主动发送
}
else
{
读数据
}
B、写
TIMEVAL tv01 = {0, 1};//1ms钟延迟,实际为9-10毫秒
int nSelectRet;
int nErrorCode;
FD_SET fdw = {1, sConnect};
nSelectRet=::select(0, NULL, NULL,&fdw, &tv01);//检查可写状态
if(SOCKET_ERROR==nSelectRet)
{
nErrorCode=WSAGetLastError();
TRACE("select write status errorcode=%d",nErrorCode);
::closesocket(sConnect);
//goto 重新连接(客户方),或服务线程退出(服务方);
}
if(nSelectRet==0)//超时发生,缓冲满或网络忙
{
//继续查写状态或查读状态
}
else
{
//发送
}
5、改变TCP收发缓冲区大小
系统默认为8192,利用如下方式可改变。
SOCKET sConnect;
sConnect=::socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
int nrcvbuf=1024*20;
int err=setsockopt(
sConnect,
SOL_SOCKET,
SO_SNDBUF,//写缓冲,读缓冲为SO_RCVBUF
(char *)&nrcvbuf,
sizeof(nrcvbuf));
if (err != NO_ERROR)
{
TRACE("setsockopt Error!\n");
}
在设置缓冲时,检查是否真正设置成功用
int getsockopt(
SOCKET s,
int level,
int optname,
char FAR *optval,
int FAR *optlen
);
6、服务方同一端口多IP地址的bind和listen
在可靠性要求高的应用中,要求使用双网和多网络通道,再服务方很容易实现,用如下方式可建立客户对本机所有IP地址在端口3024下的请求服务。
SOCKET hServerSocket_DS=INVALID_SOCKET;
struct sockaddr_in HostAddr_DS;//服务器主机地址
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash