setsockopt函数使用,setsockopt参数详解
1.如果要从已经处于建立状态的套接字(一般用端口号和标识符区分)调用closesocket后继续重用套接字(一般不会立即关闭,要经历TIME_WAIT的过程):
BOOL bReuseaddr=TRUE
setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(const char*) bReuseaddr,sizeof(BOOL));
2.如果您希望在调用closesocket后强制关闭已连接的套接字,请不要体验
时间等待程序:
BOOL bDontLinger=FALSE
setsockopt(s,SOL_SOCKET,SO_DONTLINGER,(const char*) bDontLinger,sizeof(BOOL));
3.在SEND () send()、recv()的过程中,有时由于网络条件等原因,收发无法预期,设置了收发时限:
int nNetTimeout=1000//1秒
//发送时间限制
setsockopt(socket,SOL _ S0CKET,SO_SNDTIMEO,(char *) nNetTimeout,sizeof(int));
//接收时间限制
setsockopt(socket,SOL _ S0CKET,SO_RCVTIMEO,(char *) nNetTimeout,sizeof(int));
4.send()时,返回的是实际发出的字节(同步)或发送到socket buffer的字节(异步);系统默认状态是8688字节(约8.5k)收发一次;实际过程中收发数据量比较大,可以设置socket缓冲区,避免send () send()、recv()不断循环收发:
//接收缓冲区
int nRecvBuf=32 * 1024//设置为32K
setsockopt(s,SOL_SOCKET,SO_RCVBUF,(const char*) nRecvBuf,sizeof(int));
//发送缓冲区
int nSendBuf=32 * 1024//设置为32K
setsockopt(s,SOL_SOCKET,SO_SNDBUF,(const char*) nSendBuf,sizeof(int));
5.如果在发送数据时,希望从系统缓冲区到套接字缓冲区的复制不会影响程序的性能:
int nZero=0;
setsockopt(socket,SOL _ S0CKET,SO_SNDBUF,(char *) nZero,sizeof(nZero));
6.同上,在recv()中完成上述函数(默认情况下,将socket缓冲区的内容复制到系统缓冲区):
int nZero=0;
setsockopt(socket,SOL _ S0CKET,SO_RCVBUF,(char *) nZero,sizeof(int));
7.通常,当发送UDP数据报时,希望该套接字发送的数据具有广播特征:
BOOL bBroadcast=TRUE
setsockopt(s,SOL_SOCKET,SO_BROADCAST,(const char*) bBroadcast,sizeof(BOOL));
8.在客户端连接服务器的过程中,如果非阻塞模式的socket处于connect()过程中,可以设置connect()延迟,直到调用accpet()为止(该函数设置只在非阻塞过程中起显著作用,在阻塞的函数调用中不起作用)
BOOL bConditionalAccept=TRUE
setsockopt(s,SOL_SOCKET,SO_CONDITIONAL_ACCEPT,(const char *)bconditionaccept,sizeof(BOOL));
9.如果在发送数据的过程中调用了close socket()(send()没有完成,还有数据没有发送),我们之前通常采取的措施是‘从容关闭’shut down(s,SD_BOTH),但是数据肯定是丢失了。如何设置程序以满足特定应用的要求(即发送完未完成的数据后关闭套接字)?
结构逗留{
u _ short l _ onoff
u _ short l _ linger
};
灵儿m _ sLinger
m _ slinger . l _ onoff=1;//(调用closesocket()时允许停留,但仍有数据要发送)
//如果m _ slinger . l _ onoff=0;功能与2相同。);
m _ slinger . l _ linger=5;//(允许的停留时间为5秒)
setsockopt(s,SOL_SOCKET,SO_LINGER,(const char*) m_sLinger,sizeof(LINGER));
注:1。在设置了停留延迟的情况下,对于非阻塞套接字来说用处不大,最好不要使用;
2.如果想让程序不经历SO_LINGER,需要设置SO_DONTLINGER或者设置L _ ONOFF=0;
10.另一个较少使用的程序是可以在SDI或Dialog程序中记录socket的调试信息:
(我前不久做过这个功能的测试,模式信息可以保存,包括socket建立时的参数。这
可以记录特定的协议以及错误代码)
BOOL bDebug=TRUE
setsockopt(s,SOL_SOCKET,SO_DEBUG,(const char*) bDebug,sizeof(BOOL));
1.附加:缓冲区大小常由setsockopt()设置,但不能满足数据传输要求。
我的习惯是写一个处理网络缓冲的类,动态分配内存。下面我就写这个类,希望是对的。
初学者很有帮助:
//是模仿String重写的。
//==============================================================================
//二进制数据,主要用于收发网络缓冲区的数据
//cnetiobffer以MFC(消歧义)类c环!c环!c形环的源代码作为蓝本改写而成,用法与c环!c环!c形环类似,
//但是壳聚糖缓冲剂公司中存放的是纯粹的二进制数据,/0 并不作为它的结束标志。
//其数据长度可以通过GetLength()获得,缓冲区地址可以通过运算符LPBYTE(字节)获得。
===ytet-伊甸园字幕组=-翻译:粒粒尘紫月猫姐风景校对
//版权所有全视公司.保留所有权利。
//模块:网络对象
//文件:simpleiobuffer。h
//作者:gdy 119
//电子邮件:8751网站管理员@126.com
//日期:2004年11月26日
===ytet-伊甸园字幕组=-翻译:粒粒尘紫月猫姐风景校对
//NetIOBuffer.h
#ifndef _NETIOBUFFER_H
#define _ netiobuffer _ h
===破烂熊乐园倾情奉献=================破烂熊乐园倾情奉献=============================================破烂熊乐园倾情奉献
#设置最大缓冲区长度1024*1024
===破烂熊乐园倾情奉献=================破烂熊乐园倾情奉献=============================================破烂熊乐园倾情奉献
//主要用来处理网络缓冲的数据
壳聚糖缓冲剂级战列舰
{
受保护:
S7-1200可编程控制器:
内部m _长度
内部蒙托塔伦思
临界_截面_cs:
void init valbers();
观众:
cnetiobffer();
cnetiobifer(const LP byte lb byte,int nlngth);
cnetiobifer(const cnetiobifer binary src);
virtual ~ cnetiobfer();
===破烂熊乐园倾情奉献=============破烂熊乐园倾情奉献=================================================破烂熊乐园倾情奉献
BOOL CopyData(const LPBYTE lbbyte,int nlngth);
bool concat data(const LP byte lb byte,int lnngth);
空的重置缓冲区();
int get length()常量;
bool setlength(int nln);
LP byte getcurpos();
int getrmainlen();
bool isempty()const;
LPBYTE()常量运算符;
静态获取axlength(){返回最大缓冲区长度}
const cnetiobuffer运算符=(const cnetiobuffer buf src);
}:
#endif //
//NetOBuffer.cpp:实施cnobuffer类。
===ytet-伊甸园字幕组=-翻译:粒粒粒尘紫月猫姐风景校对:阿衡时间轴:邦德猪
#包括stdafx.h
#包括netiobuffer。h
===ytet-伊甸园字幕组=-翻译:粒粒粒尘紫月猫姐风景校对:阿衡时间轴:邦德猪
===ytet-伊甸园字幕组=-翻译:粒粒粒尘紫月猫姐风景校对:阿衡时间轴:邦德猪
//构造/销毁
cnetiobifer:cnetiobifer()
{
init val bers();
}
cnetiobifer:cnetiobifer(const LP byte lb byte,int nlength)
{
init val bers();
CopyData(lbbyte、nlngth);
}
cnetiobifer:~ cnetiobifer()
{
删除[]m _ pbin data;
m_pbinData=NULL:
deletecriticalsection函数(m_cs):
}
cnetiobifer:cnetiobifer(const cnetiobifer binary src)
{
init val bers();
CopyData(binarySrc,binarySrc).get length());
}
见cnetiobffer:init validbers()
{
m_pbinData=NULL:
m _ nlngth=0;
m_nTotalLength=最大缓冲区_长度:
if(m_pbinData==NULL)
{
m _ pbindata=new新字节[m _ ntotallength];
断言(m_pbinData!=空:
}
初始化部分(m _ cs):
}
请参阅cnetiobffer:reseiobuffer()
{
entercriticalsection函数(m_cs):
m _ nlngth=0;
memset(m_pbinData,0,m _ ntotallength);
leavecriticalsection函数(m_cs):
}
bool cnetiobffer:复制数据(const lpbyte lbbyte,int nlength)
{
如果(最大缓冲区长度)
返回错误的
复位缓冲区():
entercriticalsection函数(m_cs):
memcpy(m_pbinData、lbbyte、nlngth);
m _ nlength=nlength
leavecriticalsection函数(m_cs):
返回真实的
}
bool cnetiobffer:concat data(const LP byte lb byte,int nlength)
{
if(m _ nlngth最大缓冲区_长度)
返回错误的
entercriticalsection函数(m_cs):
memcpy(m _ pbindata m _ nlngth,lbbyte,lnngth);
m _ nlength=nlength
leavecriticalsection函数(m_cs):
返回真实的
}
int cnetiobifer:get ength()const
{
返回m _长度
}
bool cnetiobffer:setlength(int nln)
{
if(nln最大缓冲区长度)
返回错误的
entercriticalsection函数(m_cs):
m _ nlength=nlen
leavecriticalsection函数(m_cs):
返回真实的
}
lpbyte techobffer:get uros()
{
if(m _ nlength max _ buffer _ length)
返回(m _ pbin data m _ nlngth);
其他语句
返回空:
}
cnetiobffer:lpbyte()运算子常数
{
返回m _ pbindata
}
int cnetiobffer:getrmainlen()
{
返回最大缓冲区长度-m _ n长度:
}
bool cnetiobffer:isempty()常量
{
返回m _ nlngth==0;
}
const CNetIOBuffer CNetIOBuffer:operator=(const CNetIOBuffer buffer src)
{
if( buffSrc!=这个)
{
CopyData(buffSrc,buffSrc。GetLength());
}
返回* this
}
回复:PiggyXP
事实上,我认为应该注意第5条。
int nZero=0;
setsockopt(socket,SOL _ S0CKET,SO_SNDBUF,(char *) nZero,sizeof(nZero));
记得之前有朋友讨论过,虽然socket发送成功,但实际上只是发送到了数据缓冲区,并没有真正在物理设备上发送出去;有了这个语句,发送缓冲区设置为0,也就是发送缓冲区被阻塞后,一旦返回send(当然是以阻塞绑定字来说),就可以确定数据已经在发送_的路上了,但这可能会影响系统的性能。
收件人:桑德()
UDP也有复制过程,但是UDP包的最大限制是64K;
TCP_NODELAY一般用在普通数据流上;
12.发送数据时,通常是在系统缓冲区满了之后发送。现在只要系统设置好了
缓冲区中有数据时立即发送数据:
BOOL bNodelay=TRUE
SetSockOpt(s,IPPROTO_TCP,TCP_NODELAY,(const char*) bNodelayt,sizeof(BOOL));
回复:od4ys(峰峰)
当setoptsock()函数设置为端口重用时,很容易损害一些没有单独绑定模式的程序。
比如老的ping icmp门,经过简单的嗅探器,接收到数据包,然后设置setoptsock bind web服务,然后建立一个cmd进程绑定和端口80。