linux socket服务器框架

高性能跨平台(Win&Linux;)网络通信框架 HP-Socket 高性能跨平台(Win&Linux;)网络通信框架 HP-Socket 没有最好只有更好, 非源代码,太大无法上传,有网址可自行下载完整包 。 HP-Socket 是一套通用的高性能 TCP/UDP/HTTP 通信框架,包含服务端组件、客户端组件和Agent组件,广泛适用于各种不同应用场景的 TCP/UDP/HTTP 通信系统,提供 C/C++、C#、Delphi、E(易语言)、Java、Python 等编程语言接口。HP-Socket 对通信层实现完全封装,应用程序不必关注通信层的任何细节;HP-Socket 提供基于事件通知模型的 API 接口,能非常简单高效地整合到新旧应用程序中。 为了让使用者能方便快速地学习和使用 HP-Socket ,迅速掌握框架的设计思想和使用方法,特此精心制作了大量 Demo 示例(如:PUSH 模型示例、PULL 模型示例、PACK 模型示例、性能测试示例以及其它编程语言示例)。HP-Socket 目前支持 Windows 和 Linux 平台。 HP-Socket 的设计充分注重功能、通用型、易用性与伸缩性; HP-Socket 项目主页:http://www.oschina.net/p/hp-socket 立即下载
思考一种高性能的服务器处理框架
1、首先需要一个内存池,目的在于:
·减少频繁的分配和释放,提高性能的同时,还能避免内存碎片的问题;
·能够存储变长的数据,不要很傻瓜地只能预分配一个最大长度;
·基于SLAB算法实现内存池是一个好的思路:分配不同大小的多个块,请求时返回大于请求长度的最小块即可,对于容器而言,处理固定块的分配和回收,相当 容易实现。当然,还要记得需要设计成线程安全的,自旋锁比较好,使用读写自旋锁就更好了。
·分配内容的增长管理是一个问题,比如第一次需要1KB空间,随着数据源源不断的写入,第二次就需要4KB空间了。扩充空间容易实现,可是扩充的时候必然 涉及数据拷贝。甚至,扩充的需求很大,上百兆的数据,这样就不好办了。暂时没更好的想法,可以像STL一样,指数级增长的分配策略,拷贝数据虽不可避免, 但是起码重分配的几率越来越小了。
·上面提到的,如果是上百兆的数据扩展需要,采用内存映射文件来管理是一个好的办法:映射文件后,虽然占了很大的虚拟内存,但是物理内存仅在写入的时候才 会被分配,加上madvice()来加上顺序写的优化建议后,物理内存的消耗也会变小。
·用string或者vector去管理内存并不明智,虽然很简单,但服务器软件开发中不适合使用STL,特别是对稳定性和性能要求很高的情况下。

2、第二个需要考虑的是对象池,与内存池类似:
·减少对象的分配和释放。其实C++对象也就是struct,把构造和析构脱离出来手动初始化和清理,保持对同一个缓冲区的循环利用,也就不难了。
·可以设计为一个对象池只能存放一种对象,则对象池的实现实际就是固定内存块的池化管理,非常简单。毕竟,对象的数量非常有限。

3、第三个需要的是队列:
·如果可以预料到极限的处理能力,采用固定大小的环形队列来作为缓冲区是比较不错的。一个生产者一个消费者是常见的应用场景,环形队列有其经典的“锁无 关”算法,在一个线程读一个线程写的场景下,实现简单,性能还高,还不涉及资源的分配和释放。好啊,实在是好!
·涉及多个生产者消费者的时候,tbb::concurent_queue是不错的选择,线程安全,并发性也好,就是不知道资源的分配释放是否也管理得足 够好。

4、第四个需要的是映射表,或者说hash表:
·因为epoll是事件触发的,而一系列的流程可能是分散在多个事件中的,因此,必须保留下中间状态,使得下一个事件触发的时候,能够接着上次处理的位置 继续处理。要简单的话,STL的hash_map还行,不过得自己处理锁的问题,多线程环境下使用起来很麻烦。
·多线程环境下的hash表,最好的还是tbb::concurent_hash_map。

5、核心的线程是事件线程:
·事件线程是调用epoll_wait()等待事件的线程。例子代码里面,一个线程干了所有的事情,而需要开发一个高性能的服务器的时候,事件线程应该专 注于事件本身的处理,将触发事件的socket句柄放到对应的处理队列中去,由具体的处理线程负责具体的工作。

6、accept()单独一个线程:
·服务端的socket句柄(就是调用bind()和listen()的这个)最好在单独的一个线程里面做accept(),阻塞还是非阻塞都无所谓,相 比整个服务器的通讯,用户接入的动作只是很小一部分。而且,accept()不放在事件线程的循环里面,减少了判断。

7、接收线程单独一个:
·接收线程从发生EPOLLIN事件的队列中取出socket句柄,然后在这个句柄上调用recv接收数据,直到缓冲区没有数据为止。接收到的数据写入以 socket为键的hash表中,hash表中有一个自增长的缓冲区,保存了客户端发过来的数据。
·这样的处理方式适合于客户端发来的数据很小的应用,比如HTTP服务器之类;假设是文件上传的服务器,则接受线程会一直处理某个连接的海量数据,其他客 户端的数据处理产生了饥饿。所以,如果是文件上传服务器一类的场景,就不能这样设计。

8、发送线程单独一个:
·发送线程从发送队列获取需要发送数据的SOCKET句柄,在这些句柄上调用send()将数据发到客户端。队列中指保存了SOCKET句柄,具体的信息 还需要通过socket句柄在hash表中查找,定位到具体的对象。如同上面所讲,客户端信息的对象不但有一个变长的接收数据缓冲区,还有一个变长的发送 数据缓冲区。具体的工作线程发送数据的时候并不直接调用send()函数,而是将数据写到发送数据缓冲区,然后把SOCKET句柄放到发送线程队列。
·SOCKET句柄放到发送线程队列的另一种情况是:事件线程中发生了EPOLLOUT事件,说明TCP的发送缓冲区又有了可用的空间,这个时候可以把 SOCKET句柄放到发送线程队列,一边触发send()的调用;
·需要注意的是:发送线程发送大量数据的时候,当频繁调用send()直到TCP的发送缓冲区满后,便无法再发送了。这个时候如果循环等待,则其他用户的 发送工作受到影响;如果不继续发送,则EPOLL的ET模式可能不会再产生事件。解决这个问题的办法是在发送线程内再建立队列,或者在用户信息对象上设置 标志,等到线程空闲的时候,再去继续发送这些未发送完成的数据。

9、需要一个定时器线程:
·一位将epoll使用的高手说道:“单纯靠epoll来管理描述符不泄露几乎是不可能的。完全解决方案很简单,就是对每个fd设置超时时间,如果超过 timeout的时间,这个fd没有活跃过,就close掉”。
·所以,定时器线程定期轮训整个hash表,检查socket是否在规定的时间内未活动。未活动的SOCKET认为是超时,然后服务器主动关闭句柄,回收 资源。

10、多个工作线程:
·工作线程由接收线程去触发:每次接收线程收到数据后,将有数据的SOCKET句柄放入一个工作队列中;工作线程再从工作队列获取SOCKET句柄,查询 hash表,定位到用户信息对象,处理业务逻辑。
·工作线程如果需要发送数据,先把数据写入用户信息对象的发送缓冲区,然后把SOCKET句柄放到发送线程队列中去。
·对于任务队列,接收线程是生产者,多个工作线程是消费者;对于发送线程队列,多个工作线程是生产者,发送线程是消费者。在这里需要注意锁的问题,如果采 用tbb::concurrent_queue,会轻松很多。

11、仅仅只用scoket句柄作为hash表的键,并不够:
·假设这样一种情况:事件线程刚把某SOCKET因发生EPOLLIN事件放入了接收队列,可是随即客户端异常断开了,事件线程又因为EPOLLERR事 件删除了hash表中的这一项。假设接收队列很长,发生异常的SOCKET还在队列中,等到接收线程处理到这个SOCKET的时候,并不能通过 SOCKET句柄索引到hash表中的对象。
·索引不到的情况也好处理,难点就在于,这个SOCKET句柄立即被另一个客户端使用了,接入线程为这个SCOKET建立了hash表中的某个对象。此 时,句柄相同的两个SOCKET,其实已经是不同的两个客户端了。极端情况下,这种情况是可能发生的。
·解决的办法是,使用socket fd + sequence为hash表的键,sequence由接入线程在每次accept()后将一个整型值累加而得到。这样,就算SOCKET句柄被重用,也 不会发生问题了。

12、监控,需要考虑:
·框架中最容易出问题的是工作线程:工作线程的处理速度太慢,就会使得各个队列暴涨,最终导致服务器崩溃。因此必须要限制每个队列允许的最大大小,且需要 监视每个工作线程的处理时间,超过这个时间就应该采用某个办法结束掉工作线程。

对于linux socket与epoll配合相关的一些心得记录 2008-07-29 17:57

setsockopt(s,SOL_SOCKET,SO_RCVBUF,(const char*)&nRecvBuf,sizeof(int));
1、通过上面语句可以简单设置缓冲区大小,测试证明:跟epoll结合的时候只有当 单次发送的数据全被从缓冲区读完毕之后才会再次被触发,多次发送数据如果没有 读取完毕当缓冲区未满的时候数据不会丢失,会累加到后面。
2、 如果缓冲区未满,同一连接多次发送数据会多次收到EPOLLIN事件。 单次发送数据>socket缓冲区大小的数据数据会被阻塞分次发送,所以循环接收可 以用ENLIGE错误判断。
3、如果缓冲区满,新发送的数据不会触发epoll事件(也无异常),每次recv 都会为缓冲区腾出空间,只有当缓冲区空闲大小能够再次接收数据epollIN事件可 以再次被触发 接收时接收大小为0表示客户端断开(不可能有0数据包触发EPOLLIN),-1表示异 常,针对errorno进行判断可以确定是合理异常还是需要终止的异常,>0而不等于 缓冲区大小表示单次发送结束。
4、 如果中途临时调整接收缓存区大小,并且在上一次中数据没有完全接收到 用户空间,数据不会丢失,会累加在一起 所以总结起来,系统对于数据的完整性还是做了相当的保正,至于稳定性没有作更 深一步的测试

新增加:
5、如果主accept监听的soctet fd也设置为非阻塞,那么单纯靠epoll事件来驱 动的服务器模型会存在问题,并发压力下发现,每次accept只从系统中取得第一 个,所以如果恰冯多个 连接同时触发server fd的EPOLLIN事件,在返回的event数 组中体现不出来,会出现丢失事件的现象,所以当用ab等工具简单的压载就会发现 每次都会有最后几条信息得 不到处理,原因就在于此,我现在的解决办法是将 server fd的监听去掉,用一个线程阻塞监听,accept成功就处理检测client fd, 然后在主线程循环监听client事件,这样epoll在边缘模式下出错的概率就小,测 试表明效果明显
6、对于SIG部分信号还是要做屏蔽处理,不然对方socket中断等正常事件都会引起 整个服务的退出
7、sendfile(fd, f->SL->sendBuffer.inFd, (off_t *)&f->SL->sendBuffer.offset, size_need);注意sendfile函数的地三个变量是传 送地址,偏移量会自动增加,不需要手动再次增加,否则就会出现文件传送丢失现象
8、单线程epoll驱动模型误解:以前我一直认为单线程是无法处理web服务器这样 的有严重网络延迟的服务,但nginx等优秀服务器都是机遇事件驱动 模型,开始我 在些的时候也是担心这些问题,后来测试发现,当client socket设为非阻塞模式 的时候,从读取数据到解析http协议,到发送数据均在epoll的驱动下速度非常 快,没有必要采用多线程,我的单核 cpu(奔三)就可以达到 10000page/second,这在公网上是远远无法达到的一个数字(网络延迟更为严 重),所以单线程的数据处理能力已经很 高了,就不需要多线程了,所不同的是 你在架构服务器的时候需要将所有阻塞的部分拆分开来,当epoll通知你可以读取 的时候,实际上部分数据已经到了 socket缓冲区,你所读取用的事件是将数据从 内核空间拷贝到用户空间,同理,写也是一样的,所以epoll重要的地方就是将这 两个延时的部分做了类似 的异步处理,如果不需要处理更为复杂的业务,那单线 程足以满足1000M网卡的最高要求,这才是单线程的意义。 我以前构建的web服务器就没有理解epoll,采用epoll的边缘触发之程处后怕事件 丢失,或者单线理阻塞,所以自己用多线程构建了一个任务调度器, 所有收 到的事件统统压进任无调度器中,然后多任务处理,我还将read和write分别用两 个调度器处理,并打算如果中间需要特殊的耗时的处理就增加一套 调度器,用少量线程+epoll的方法来题高性能,后来发现read和write部分调度器是多余 的,epoll本来就是一个事件调度器,在后面再次缓存 事件分部处理还不如将 epoll设为水平模式,所以多此一举,但是这个调度起还是有用处的 上面讲到如果中间有耗时的工作,比如数据库读写,外部资源请求(文 件,socket)等这些操作就不能阻塞在主线程里面,所以我设计的这个任务调度器 就有 用了,在epoll能处理的事件驱动部分就借用epoll的,中间部分采用模块化 的设计,用函数指针达到面相对象语言中的“委托”的作用,就可以满足不同 的需 要将任务(fd标识)加入调度器,让多线程循环执行,如果中间再次遇到阻塞就会 再次加入自定义的阻塞器,检测完成就加入再次存入调度器,这样就可以将 多种 复杂的任务划分开来,相当于在处理的中间环节在自己购置一个类似于epoll的事 件驱动器
9、多系统兼容:我现在倒是觉得与其构建一个多操作系统都支持的服务器不 如构建特定系统的,如果想迁移再次改动,因为一旦兼顾到多个系统的化会大大增 加系 统的复杂度,并且不能最优性能,每个系统都有自己的独有的优化选项,所 以我觉得迁移的工作量远远小于兼顾的工作量
10模块化编程,虽然用c还是要讲求一些模块化的设计的,我现在才发现几乎面相 对想的语言所能实现的所有高级特性在c里面几乎都有对应的解决办法(暂时发现 除了操作符重载),所有学过高级面相对象的语言的朋友不放把模式用c来实现, 也是一种乐趣,便于维护和自己阅读
11、养成注释的好习惯


setsockopt -设置socket

1.closesocket(一般不会立即关闭而经历TIME_WAIT的过程)后想继续重用该socket:
BOOL bReuseaddr=TRUE;
setsockopt(s,SOL_SOCKET ,SO_REUSEADDR,(const char*)&bReuseaddr,sizeof(BOOL));


2. 如果要已经处于连接状态的soket在调用closesocket后强制关闭,不经历
TIME_WAIT的过程:
BOOL bDontLinger = FALSE;
setsockopt(s,SOL_SOCKET,SO_DONTLINGER,(const char*)&bDontLinger,sizeof(BOOL));


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));


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().

微软登录OAuth 2.0授权流程 OAuth 2.0是一个关于授权的开放网络标准,它允许第三方应用获取用户数据,是目前最流行的授权机制。微软身份平台支持OAuth 2.0授权码流程,使得客户端应用程序能够获得对受保护资源(如网络API)的授权访问。这一流程在保障用户数据安全的前提下,实现了应用的便捷登录与数据共享。当用户在一个支持OAuth 2.0的应用上,希望使用微软账号进行登录时,OAuth 2.0授权流程即被触发。 阅读详情

相关推荐

国科GK7202V300芯片开发避坑指南:从uboot编译到SDK配置的12个实战问题解决

本文针对国科GK7202V300芯片开发过程中的常见难题,提供从uboot编译、SDK配置到系统部署的实战解决方案。详细解析了开发环境搭建、内核编译、驱动模块加载、根文件系统构建及烧写部署等12个关键环节的避坑指南,帮助开发者高效解决编译错误、配置冲突等典型问题,提升开发效率。

sunny的博客 234

Linux高并发服务器开发(八)Socket和TCP

服务器向客户端发送 第一次发送512字节,当客户端还没读取完全时,又发送了1024个字节,则会发生粘包。mss 最大报文长度,一般出现在三次握手的前两次,用来告知对方发送数据的最大长度。提取链接得到一个已连接的套接字,接下来用这个已连接的套接字和客户端通信。每一次读取数据后,回ack报文,报文中会携带当前缓冲区大小。tcp是打电话的模型,建立连接 使用连接 关闭连接。关闭,半关闭(只关闭应用层的收发,但底层还能收发)从已完成链接队列提取链接。bind 绑定端口号,红区有多大,还剩多少,

Lmz_0314的博客 769

Xilinx System Generator多速率系统(Multi-Rate Systems)的使用

在本实验练习中,您将学习在System Generator中如何使用多个时钟域有效地实现具有多个数据速率的设计。

白码王子小张的博客 1093

socket套接字及TCP的实现框架

Berkeley UNIX操作系统定义了一种API,它又称为套接字接口(socket interface)微软公司在其操作系统中采用了套接字接口API,形成了一个稍有不同的API,并称之为windows SocketAT&T为其UNIX系统V定义了一种API,简写为TLI(Transport Layer Interface)

2201_75441920的博客 127

Obsidian和Typora图片路径同步终极指南:告别混乱的assets文件夹

本文详细解析了Obsidian与Typora图片路径同步的终极解决方案,通过Custom Attachment Location插件实现动态路径管理,解决了两款工具间图片兼容性问题。文章提供了从基础配置到高级应用的完整指南,帮助用户告别混乱的assets文件夹,提升工作效率。

g9h0i1的博客 821

开源处理器Rocket的分支预测机制研究与性能评估(二)

Rocket是基于RISC-V指令集架构的开源处理器,具有分支预测功能,其实现了GShare分支预测机制,在分析Rocket处理器分支预测处理过程、分支预测实现原理的基础上,利用模拟器进行了性能测试,并依据测试结果,对Rocket处理器分支预测参数配置给出建议。

leishangwen的专栏 5691

Linux环境下socket服务器搭建

socket函数 domain参数:type参数protocol参数返回值:bind函数listen函数accept 函数connect函数send()与recv()read()/write() 建立socket服务器代码 建立socket客户端代码

mankeywang的博客 4087

DeepSeek与豆包无缝对接:5分钟搞定智能周报自动化(附完整代码)

本文详细介绍了如何利用DeepSeek与豆包API,快速搭建一个智能周报自动化系统。通过整合豆包平台的工作流数据,并调用DeepSeek大模型进行深度分析与内容生成,该系统能在5分钟内自动抓取、分析多源信息,并生成结构清晰、富有洞察力的团队周报,显著提升工作效率。

weixin_29029995的博客 491

linux-vsock-internals-vsock框架

转:https://terenceli.github.io/%E6%8A%80%E6%9C%AF/2020/04/18/vsock-internals。

qq_45698138的博客 3489

AI Pika 生成进击的巨人动漫分镜案例

AI Pika 生成进击的巨人动漫分镜案例 Pika 是一个使用AI生成和编辑视频的平台。

独立开发,substack顶级编辑 2573

24. SAP 标准产品里使用 OData 服务的一些细节分享

笔者在编写使用事物码 SEGW 开发 SAP OData 服务的系列步骤时,但凡遇到技术上一些疑难问题,喜欢去参照 SAP 标准产品里是如何使用 OData 服务的,不少问题都可以去参考 SAP 标准产品的 OData 服务实现细节来解决。 因此本文记录笔者在编写本教程的过程中,曾经研究过的 SAP OData 服务实现的一些细节,把这些细节分享给大家,希望能起到参考作用。 同时,教程也不断收到一些朋友在评论区留言,对于不少留言的回复,我也是拿 SAP 标准 OData 服务的实现作为论据来回复的。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 2030

Linux网络编程:socket、客户端服务器端使用socket通信(TCP)

Linux网络编程:socket、客户端服务器端使用socket通信(TCP)

坚持学习 4757

机器学习笔记 - 神经辐射场(NeRF)的简要概述

神经辐射场十分重要。在表示和渲染 3D 场景领域,神经辐射场 (NeRF) 在准确性方面取得了巨大突破。给定底层场景的多个图像,NeRF 可以从任意视点重建该场景的高分辨率、2D 渲染图。与局部光场融合 (LLFF) 和场景表示网络 (SRN) 等现有技术相比,NeRF 更能够捕获场景外观和几何形状的复杂组成部分(例如,依赖于视图的反射和复杂的材料)。NeRF的研究目的是合成同一场景不同视角下的图像。

学以致用 知行合一 1692

linux socket高性能服务器处理框架

这个博客很多东西 http://blog.youkuaiyun.com/luozhonghua2014/article/details/37041765 思考一种高性能的服务器处理框架 1、首先需要一个内存池,目的在于: ·减少频繁的分配和释放,提高性能的同时,还能避免内存碎片的问题; ·能够存储变长的数据,不要很傻瓜地只能预分配一个最大长度; ·基于SLAB算法实现内存池是一个好的思路:分配不同...

墨痕诉清风的博客 661

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

Linux socket多进程服务器框架一

重点:socket共用方法中错误码的定义以及错误码的解析 底层辅助代码 //serhelp.h #ifndef _vxser #define _vxser #ifdef __cplusplus extern "C" { #endif /** * sersocket_init - socket初始化 * @listenfd:文件描述符 * 成功返回0,失败返回错误码 * */...

weixin_34407348的博客 247

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

Linux socket多进程服务器框架三

在使用select管理服务器连接的时候: 注意1:select是可中断睡眠函数,需要屏蔽信号 注意2:必须获取select的返回值nread,每次处理完一个事件,nread需要-1 注意3:如果客户端的连接超过连接池的大小,需要关闭客户端连接 注意4:获取最大套接字的方法是每次有客户端连接过来时,在和maxfd比较,这样就不用每次select之前都遍历池,查找最大值 服务器 ...

weixin_30685047的博客 89

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

Linux socket多进程服务器框架二

客户端未解决Bug:子进程或者父进程退出的时候,我无法做到两个进程都调用clt_socket_Destory()方式释放socket句柄, 但是进程退出后,相应的资源也会释放,有一定影响,但是不大,以后我想到办法再优化。重点:客户端connect服务器方法需要单独分离出来,方便用户自己断线重连。 客户端 //clthelp.h #include &lt;stdio.h&gt; #incl...

weixin_34117211的博客 129
上一篇: new和malloc
下一篇: C语言宏定义##连接符和#符的使用
执迷的信徒
博客等级 码龄16年 245粉丝 60原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值