1.closesocket(通常不会当即关闭而经历TIME_WAIT的过程)后想继续重用该socket:
BOOL bReuseaddr=TRUE;
setsockopt(s,SOL_SOCKET ,SO_REUSEADDR,(const char*)&bReuseaddr,sizeof(BOOL));linux
2. 若是要已经处于链接状态的soket在调用closesocket后强制关闭,不经历
TIME_WAIT的过程:
BOOL bDontLinger = FALSE;
setsockopt(s,SOL_SOCKET,SO_DONTLINGER,(const char*)&bDontLinger,sizeof(BOOL));nginx
3.在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));web
4.在send()的时候,返回的是实际发送出去的字节(同步)或发送到socket缓冲区的字节
(异步);系统默认的状态发送和接收一次为8688字节(约为8.5K);在实际的过程当中发送数据
和接收数据量比较大,能够设置socket缓冲区,而避免了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. 若是在发送数据的时,但愿不经历由系统缓冲区到socket缓冲区的拷贝而影响
程序的性能:
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数据报的时候,但愿该socket发送的数据具备广播特性:
BOOL bBroadcast=TRUE;
setsockopt(s,SOL_SOCKET,SO_BROADCAST,(const char*)&bBroadcast,sizeof(BOOL));缓存
8.在client链接服务器过程当中,若是处于非阻塞模式下的socket在connect()的过程当中可
以设置connect()延时,直到accpet()被呼叫(本函数设置只有在非阻塞的过程当中有显著的
做用,在阻塞的函数调用中做用不大)
BOOL bConditionalAccept=TRUE;
setsockopt(s,SOL_SOCKET,SO_CONDITIONAL_ACCEPT,(const char*)&bConditionalAccept,sizeof(BOOL));安全
若是在发送数据的过程当中(send()没有完成,还有数据没发送)而调用了closesocket(),之前咱们
通常采起的措施是"从容关闭"shutdown(s,SD_BOTH),可是数据是确定丢失了,如何设置让程序知足具体
应用的要求(即让没发完的数据发送出去后在关闭socket)?
struct linger {
u_short l_onoff;
u_short l_linger;
};
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));服务器
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////网络
线程于进程的好处在于:
方便通讯,线程共享了代码与数据空间,因此对共享空间提供了最原始的支持
能够用线程运行完销毁的方式而不须要回收线程资源,只要进程退出,全部线程就销毁了,不须要担忧有僵尸进程的出现,也就是资源不能回收的问题。
对于并发比较高的服务器,而且每一个处理时间又不是太长的状况下,能够采用线程池的方式
在同等状况下,线程所占资源略少于进程,由于线程在访问一共享变量时,在物理内存中仅有一份此变量所占空间,如果进程间须要改写同一全局变量时,此时就会产生“写时复制”,会产生两份空间(对一个变量的改写,会形成多占用大于等于4K的物理空间)
进程于线程的好处在于:
不须要担忧太多由于访问共享资源而形成的各类同步与互斥问题,若是须要共享某部份内容,须要走专用的进程间通讯手段,也就是说对于共享空间是可控制的,不会出现随机性
不用担忧一不当心就形成函数重入的问题
在不一样的进程中,可使用不一样的ELF文件做为执行体,固然,在线程中也能够再进行fork+execv来实现这种方案
不管是线程仍是进程,其调度方式是同样的
长链接,用poll/select/epoll作多路复用的方式优缺点:
因为不会形成多线程与多进程,因此全部代码都在一个执行体内,都在同一调度单元中,节省了资源的开销,如内存的占用,进程切换的开销。
因为全部处理都在同一个调度单元内,也就是多个链接共用一个进程的时间片,若是系统中还有不少其它优先级较高进程或者实时进程,平均下来每一个链接所占用的 CPU时间就较少,且若是一个链接处于死循环中,若不加其它控制,其它链接就永远得不到响应,也就是说每一个链接的响应实时性会受到其它链接的影响。
若是对于每一个链接的处理方式不一样,会形成代码的很差控制,由于会有太多的逻辑判断。
以上三种方式,各有优缺点,主要是楼主的需求,这三种方式并不是是互斥的,能够交叉使用,灵活控制,从而最优化你的软件。固然,若是并发链接达到2000个 以上,并发处理也达到几百上千个以上(且每一个处理过程会执行很长),那么推荐你采用分布式处理,单个PC机是没法承受这种负荷的(若使用专用服务器,性能 会好一些,这个相对限制会宽一些),至少会形成响应时间过长
、、、、、、、、、、、、、、、、、、、、、、、、、、、
设置套接口的选项。 #include <winsock.h> int PASCAL FAR setsockopt( SOCKET s, int level, int optname, const char FAR* optval, int optlen); s:标识一个套接口的描述字。 level:选项定义的层次;目前仅支持SOL_SOCKET和IPPROTO_TCP层次。 optname:需设置的选项。 optval:指针,指向存放选项值的缓冲区。 optlen:optval缓冲区的长度。 注释: setsockopt()函数用于任意类型、任意状态套接口的设置选项值。尽管在不一样协议层上存在选项,但本函数仅定义了最高的“套接口”层次上的选项。选项影响套接口的操做,诸如加急数据是否在普通数据流中接收,广播数据是否能够从套接口发送等等。 有两种套接口的选项:一种是布尔型选项,容许或禁止一种特性;另外一种是整形或结构选项。容许一个布尔型选项,则将optval指向非零整形数;禁止一个选 项optval指向一个等于零的整形数。对于布尔型选项,optlen应等于sizeof(int);对其余选项,optval指向包含所需选项的整形数 或结构,而optlen则为整形数或结构的长度。SO_LINGER选项用于控制下述状况的行动:套接口上有排队的待发送数据,且 closesocket()调用已执行。参见closesocket()函数中关于SO_LINGER选项对closesocket()语义的影响。应用 程序经过建立一个linger结构来设置相应的操做特性: struct linger { int l_onoff; int l_linger; }; 为了容许SO_LINGER,应用程序应将l_onoff设为非零,将l_linger设为零或须要的超时值(以秒为单位),而后调用setsockopt()。为了容许SO_DONTLINGER(亦即禁止SO_LINGER),l_onoff应设为零,而后调用setsockopt()。 缺省条件下,一个套接口不能与一个已在使用中的本地地址捆绑(参见bind())。但有时会须要“重用”地址。由于每个链接都由本地地址和远端地址的组 合惟一肯定,因此只要远端地址不一样,两个套接口与一个地址捆绑并没有大碍。为了通知WINDOWS套接口实现不要由于一个地址已被一个套接口使用就不让它与 另外一个套接口捆绑,应用程序可在bind()调用前先设置SO_REUSEADDR选项。请注意仅在bind()调用时该选项才被解释;故此无需(但也无 害)将一个不会共用地址的套接口设置该选项,或者在bind()对这个或其余套接口无影响状况下设置或清除这一选项。 一个应用程序能够经过打开SO_KEEPALIVE选项,使得WINDOWS套接口实如今TCP链接状况下容许使用“保持活动”包。一个WINDOWS套 接口实现并非必需支持“保持活动”,可是若是支持的话,具体的语义将与实现有关,应遵照RFC1122“Internet主机要求-通信层”中第 4.2.3.6节的规范。若是有关链接因为“保持活动”而失效,则进行中的任何对该套接口的调用都将以WSAENETRESET错误返回,后续的任何调用 将以WSAENOTCONN错误返回。 TCP_NODELAY选项禁止Nagle算法。Nagle算法经过将未确认的数据存入缓冲区直到蓄足一个包一块儿发送的方法,来减小主机发送的零碎小数据 包的数目。但对于某些应用来讲,这种算法将下降系统性能。因此TCP_NODELAY可用来将此算法关闭。应用程序编写者只有在确切了解它的效果并确实需 要的状况下,才设置TCP_NODELAY选项,由于设置后对网络性能有明显的负面影响。TCP_NODELAY是惟一使用IPPROTO_TCP层的选 项,其余全部选项都使用SOL_SOCKET层。 若是设置了SO_DEBUG选项,WINDOWS套接口供应商被鼓励(但不是必需)提供输出相应的调试信息。但产生调试信息的机制以及调试信息的形式已超出本规范的讨论范围。 setsockopt()支持下列选项。其中“类型”代表optval所指数据的类型。 选项 类型 意义 SO_BROADCAST BOOL 容许套接口传送广播信息。 SO_DEBUG BOOL 记录调试信息。 SO_DONTLINER BOOL 不要由于数据未发送就阻塞关闭操做。设置本选项至关于将SO_LINGER的l_onoff元素置为零。 SO_DONTROUTE BOOL 禁止选径;直接传送。 SO_KEEPALIVE BOOL 发送“保持活动”包。 SO_LINGER struct linger FAR* 如关闭时有未发送数据,则逗留。 SO_OOBINLINE BOOL 在常规数据流中接收带外数据。 SO_RCVBUF int 为接收肯定缓冲区大小。 SO_REUSEADDR BOOL 容许套接口和一个已在使用中的地址捆绑(参见bind())。 SO_SNDBUF int 指定发送缓冲区大小。 TCP_NODELAY BOOL 禁止发送合并的Nagle算法。 setsockopt()不支持的BSD选项有: 选项名 类型 意义 SO_ACCEPTCONN BOOL 套接口在监听。 SO_ERROR int 获取错误状态并清除。 SO_RCVLOWAT int 接收低级水印。 SO_RCVTIMEO int 接收超时。 SO_SNDLOWAT int 发送低级水印。 SO_SNDTIMEO int 发送超时。 SO_TYPE int 套接口类型。 IP_OPTIONS 在IP头中设置选项。 返回值: 若无错误发生,setsockopt()返回0。不然的话,返回SOCKET_ERROR错误,应用程序可经过WSAGetLastError()获取相应错误代码。 错误代码: WSANOTINITIALISED:在使用此API以前应首先成功地调用WSAStartup()。 WSAENETDOWN:WINDOWS套接口实现检测到网络子系统失效。 WSAEFAULT:optval不是进程地址空间中的一个有效部分。 WSAEINPROGRESS:一个阻塞的WINDOWS套接口调用正在运行中。 WSAEINVAL:level值非法,或optval中的信息非法。 WSAENETRESET:当SO_KEEPALIVE设置后链接超时。 WSAENOPROTOOPT:未知或不支持选项。其中,SOCK_STREAM类型的套接口不支持SO_BROADCAST选项,SOCK_DGRAM 类型的套接口不支持SO_DONTLINGER 、SO_KEEPALIVE、SO_LINGER和SO_OOBINLINE选项。 WSAENOTCONN:当设置SO_KEEPALIVE后链接被复位。 WSAENOTSOCK:描述字不是一个套接口。 参见: bind(), getsockopt(), ioctlsocket(), socket(), WSAAsyncSelect().