设计模型
局域网UDP广播数据端UdpBroadCast.cpp
#include <tchar.h> // _T宏
#include <stdio.h>// printf sprintf
#include <iostream>// cout fstream
using namespace std;
// windows socket
#include <winsock.h>
#pragma comment (lib,"ws2_32.lib")
bool initSocketLib();
void main()
{
SOCKET sock; //socket套接字
char szMsg[] = "this is a UDP test package";//被发送的字段
// 1.启动SOCKET库,版本为2.0
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 2, 0 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( 0 != err ) {
cout<<"Socket2.0初始化失败,Exit!";
return;
}
if (LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 0 ) { // 检查Socket库的版本是否为2.0
WSACleanup( );
return;
}
// 2.创建socket
sock = socket( AF_INET, SOCK_DGRAM, IPPROTO_IP/*虚拟IP*/);
if (INVALID_SOCKET == sock ) {
cout<<"Socket 创建失败,Exit!";
return;
}
// 3.设置该套接字为广播类型,
bool opt = true;
setsockopt(sock, SOL_SOCKET, SO_BROADCAST/*广播*/, reinterpret_cast<char FAR *>(&opt), sizeof(opt));
// 4.设置发往的地址
sockaddr_in addrto;
memset(&addrto,0,sizeof(addrto));
addrto.sin_family = AF_INET; // 地址类型为internetwork
addrto.sin_addr.s_addr = INADDR_BROADCAST; // 设置ip为广播地址
addrto.sin_port = htons(7861); // 端口号为7861
int nlen=sizeof(addrto);
unsigned int uIndex = 1;
while(true) {
Sleep(1000);
//向广播地址发送消息
if( sendto(sock, szMsg, strlen(szMsg), 0, (sockaddr*)&addrto,nlen)== SOCKET_ERROR ) {
cout<<WSAGetLastError()<<endl;
}
else {
cout<<uIndex++<<":an UDP package is sended."<<endl;
}
}
if (!closesocket(sock)) { // 关闭套接字
WSAGetLastError();
return;
}
if (!WSACleanup()) { // 关闭Socket库
WSAGetLastError();
return;
}
return;
}
bool initSocketLib()
{
WSADATA Data;
//初始化windows Socket Dll
int status = WSAStartup(MAKEWORD(1,1),&Data);
if (0!=status)
{
printf(_T("初始化失败\n"));
return false;
}
return true;
}
局域网UDP接收广播数据端Receive.cpp
#include <tchar.h> // _T宏
#include <stdio.h>// printf sprintf
#include <iostream>// cout fstream
using namespace std;
// windows socket
#include <winsock.h>
#pragma comment (lib,"ws2_32.lib")
bool initSocketLib();
void main()
{
if(!initSocketLib())
return;
// 初始化本地客户端套接字
SOCKET serSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(serSocket == INVALID_SOCKET)
{
printf("socket error !");
return ;
}
// "本地"的服务端地址映射(IP:port)
sockaddr_in serAddr;
serAddr.sin_family = AF_INET;
serAddr.sin_port = htons(7861);
serAddr.sin_addr.S_un.S_addr = inet_addr("192.168.0.53");// 因为这是远程机器,客户端也不在本机上,所以绑定实际的物理地址
if(bind(serSocket, (sockaddr *)&serAddr, sizeof(serAddr)) == SOCKET_ERROR)
{
printf("bind error !");
closesocket(serSocket);
return ;
}
sockaddr_in remoteAddr;
int nAddrLen = sizeof(remoteAddr);
while (true)
{
char recvData[255];
int ret = recvfrom(serSocket, recvData, 255, 0, (sockaddr *)&remoteAddr, &nAddrLen);
if (ret > 0)
{
recvData[ret] = 0x00;
printf("接受到一个连接:%s \r\n", inet_ntoa(remoteAddr.sin_addr));
printf(recvData);
}
//char * sendData = "一个来自服务端的UDP数据包\n";
//sendto(serSocket, sendData, strlen(sendData), 0, (sockaddr *)&remoteAddr, nAddrLen);
}
closesocket(serSocket);
WSACleanup();
return ;
}
bool initSocketLib()
{
WSADATA Data;
//初始化windows Socket Dll
int status = WSAStartup(MAKEWORD(1,1),&Data);
if (0!=status)
{
printf(_T("初始化失败\n"));
return false;
}
return true;
}
setsockopt函数
该 setsockopt的功能设置一个套接字选项。
句法
C ++
int setsockopt(
_In_ SOCKET s,
_In_ int level,
_In_ int optname,
_In_ const char * optval,
_In_ int optlen
);
参数
s [in]
标识套接字的描述符。
水平 [in]
定义选项的级别(例如,SOL_SOCKET)。
optname [in]
要为其设置值的套接字选项(例如,SO_BROADCAST)。所述OPTNAME参数必须在规定的范围内所定义的套接字选项级别,或行为是未定义的。
optval [in]
指向缓冲区的指针,其中指定了所请求的选项的值。
optlen [in]
由optval参数指向的缓冲区的大小(以字节为单位)。
返回值
如果没有发生错误,则 setsockopt将返回零。否则返回值SOCKET_ERROR,并通过调用WSAGetLastError来检索特定的错误代码 。
错误代码 | 含义 |
在使用此功能之前,必须发生成功的 WSAStartup调用。 | |
网络子系统失败。 | |
optval参数指向的缓冲区不在进程地址空间的有效部分或 optlen参数太小。 | |
正在进行阻止Windows Sockets 1.1呼叫,或者服务提供商仍在处理回调函数。 | |
的电平的参数是无效的,或者在缓冲器中的信息指向的optval的参数是无效的。 | |
设置SO_KEEPALIVE时,连接已超时。 | |
该选项对于指定的提供程序或套接字是未知的或不受支持的(请参阅SO_GROUP_PRIORITY限制)。 | |
SO_KEEPALIVE设置后,连接已被重置。 | |
描述符不是套接字。 |
错误代码 | 含义 |
在使用此功能之前,必须发生成功的 WSAStartup调用。 | |
网络子系统失败。 | |
optval参数指向的缓冲区不在进程地址空间的有效部分或 optlen参数太小。 | |
正在进行阻止Windows Sockets 1.1呼叫,或者服务提供商仍在处理回调函数。 | |
的电平的参数是无效的,或者在缓冲器中的信息指向的optval的参数是无效的。 | |
设置SO_KEEPALIVE时,连接已超时。 | |
该选项对于指定的提供程序或套接字是未知的或不受支持的(请参阅SO_GROUP_PRIORITY限制)。 | |
SO_KEEPALIVE设置后,连接已被重置。 | |
描述符不是套接字。 |
备注
备注
的 setsockopt的函数设置用于与任何类型的插座,在任何状态相关联的套接字选项的当前值。虽然选项可以存在于多个协议级别,但它们始终位于最上层的套接字级别。选项影响套接字操作,例如在正常数据流中是否接收到加急数据(例如,OOB数据),以及是否可以在套接字上发送广播消息。
注意: 如果 setsockopt的功能是之前调用 绑定功能,TCP / IP选项将不会被直到使用TCP / IP检查 结合进行。在这种情况下, setsockopt函数调用将始终成功,但由于早期的 setsockopt调用失败, 绑定函数调用可能会 失败。
注意 如果一个套接字被打开,将进行一个 setsockopt调用,然后进行一个 sendto调用,Windows Sockets执行一个隐式的 绑定函数调用。
有两种类型的套接字选项:启用或禁用特性或行为的布尔选项,以及需要整数值或结构的选项。要启用布尔选项,optval参数指向非零整数。要禁用选项optval指向等于零的整数。对于布尔选项,optlen参数应该等于sizeof(int)
。对于其他选项,optval指向包含该选项所需值的整数或结构,optlen是整数或结构的长度。
下表列出了setsockopt函数支持的一些常用选项。“类型”列标识由optval参数寻址的数据类型。“说明”列提供了有关套接字选项的一些基本信息。有关套接字选项和更详细信息(例如默认值)的更完整列表,请参阅“ 套接字选项”下的详细主题。
level = SOL_SOCKET
值 | 类型 | 描述 |
SO_BROADCAST | BOOL | 配置发送广播数据的套接字。 |
SO_CONDITIONAL_ACCEPT | BOOL | 允许传入连接被应用程序接受或拒绝,而不是协议栈。 |
SO_DEBUG | BOOL | 启用调试输出。Microsoft提供商目前不输出任何调试信息。 |
SO_DONTLINGER | BOOL | 不阻止关闭等待未发送的数据。设置此选项等同于将l_onoff设置为零时设置SO_LINGER 。 |
SO_DONTROUTE | BOOL | 设置传出数据是否应在套接字绑定的接口上发送,而不是在某个其他接口上发送。ATM套接字不支持此选项(导致错误)。 |
SO_GROUP_PRIORITY | INT | 保留。 |
BOOL | 允许为套接字连接发送保持活动数据包。ATM套接字不支持(导致错误)。 | |
SO_LINGER | 萦绕 | 如果不存在数据,则关闭。 |
SO_OOBINLINE | BOOL | 表示外部数据应与常规数据一致返回。此选项仅适用于支持带外数据的面向连接的协议。有关此主题的讨论,请参阅无 协议独立的带外数据。 |
SO_RCVBUF | INT | 指定保留接收的每个套接字缓冲区总数。 |
SO_REUSEADDR | BOOL | 允许套接字绑定到已经在使用的地址。有关更多信息,请参阅 绑定。不适用于ATM插座。 |
BOOL | 使套接字被绑定以进行独占访问。不需要管理权限。 | |
SO_RCVTIMEO | DWORD | 设置阻止接收呼叫的超时(以毫秒为单位)。 |
SO_SNDBUF | INT | 指定为发送预留的每个套接字缓冲区总数。 |
SO_SNDTIMEO | DWORD | 阻塞发送呼叫的超时(以毫秒为单位)。 |
SO_UPDATE_ACCEPT_CONTEXT | INT | 使用监听套接字的上下文更新接受套接字。 |
PVD_CONFIG | 服务提供者依赖 | 此对象存储与套接字s关联的服务提供商的配置信息。该数据结构的确切格式是特定于服务提供商。 |
有关level = SOL_SOCKET的套接字选项的更完整和详细的信息,请参阅SOL_SOCKET套接字选项。
level = IPPROTO_TCP
值 | 类型 | 描述 |
TCP_NODELAY | BOOL | 此套接字选项包括与Windows Sockets 1.1的向后兼容性 |
有关level = IPPROTO_TCP的套接字选项的更完整和详细的信息,请参阅IPPROTO_TCP套接字选项。
level = NSPROTO_IPX
值 | 类型 | 描述 |
IPX_PTYPE | INT | 设置IPX包类型。 |
IPX_FILTERPTYPE | INT | 设置接收过滤器包类型 |
IPX_STOPFILTERPTYPE | INT | 停止过滤使用IPX_FILTERTYPE设置的过滤器类型 |
IPX_DSTYPE | INT | 在发送的每个数据包上设置SPX头中数据流字段的值。 |
IPX_EXTENDED_ADDRESS | BOOL | 设置是否启用扩展寻址。 |
IPX_RECVHDR | BOOL | 设置协议头是否在所有接收头上发送。 |
IPX_RECEIVE_BROADCAST | BOOL | 表示广播报文很可能在套接字上。默认设置为TRUE。不使用广播的应用程序应将其设置为FALSE以获得更好的系统性能。 |
IPX_IMMEDIATESPXACK | BOOL | 指示SPX连接在发送ACK之前不会延迟。没有来回流量的应用程序应将此设置为TRUE,以提高性能。 |
有关level = NSPROTO_IPX的套接字选项的更完整和详细的信息,请参阅NSPROTO_IPX套接字选项。
setsockopt不支持的BSD选项 如下表所示。
值 | 类型 | 描述 |
SO_ACCEPTCONN | BOOL | 返回套接字是否处于侦听模式。此选项仅适用于面向连接的协议。该套接字选项不支持该设置。 |
SO_RCVLOWAT | INT | 包括BSD UNIX的套接字选项,用于向后兼容。此选项设置套接字输入操作要处理的最小字节数。 |
SO_SNDLOWAT | INT | 包括BSD UNIX的套接字选项,用于向后兼容。此选项设置套接字输出操作要处理的最小字节数。 |
SO_TYPE | INT | 返回给定套接字的套接字类型(SOCK_STREAM或SOCK_DGRAM,例如套接字类型的设置不支持此套接字选项。 |
SO_CONDITIONAL_ACCEPT
将此套接字选项设置为TRUE会延迟连接的确认,直到调用WSAAccept条件函数为止 。如果为FALSE,则在调用条件功能之前可以接受连接,但如果条件功能拒绝该呼叫,则连接将被断开。在调用listen函数之前必须设置此选项 ,否则返回WSAEINVAL。SO_CONDITIONAL_ACCEPT仅支持TCP和ATM。
默认情况下,TCP将SO_CONDITIONAL_ACCEPT设置为FALSE,因此默认情况下,将在WSAAccept条件函数被调用之前接受连接 。当设置为TRUE时,必须在TCP连接超时之内进行条件决定。CF_DEFER连接仍然会超时。
默认情况下,ATM将SO_CONDITIONAL_ACCEPT设置为TRUE。
SO_DEBUG
如果应用程序设置了SO_DEBUG选项,Windows Sockets服务提供商将被鼓励(但不是必需)提供输出调试信息。用于生成调试信息及其形式的机制超出了本文档的范围。
SO_GROUP_PRIORITY
保留以备将来使用套接字组。组优先级表示指定套接字相对于套接字组内其他套接字的相对优先级。值是非负整数,零对应于最高优先级。优先级值代表底层服务提供商关于如何分配潜在稀缺资源的提示。例如,当两个或更多个套接字都准备好传输数据时,最高优先级套接字(SO_GROUP_PRIORITY的最低值)应首先进行处理,其余的根据其相对优先级依次进行服务。
应用程序可以通过打开SO_KEEPALIVE套接字选项来请求TCP / IP提供商启用TCP连接上的保持活动数据包。Windows Sockets提供程序不需要支持使用keep-alives。如果是这样,精确的语义是实现特定的,但应符合关于IETF网站上提供的RFC 1122中规定的Internet主机 - 通信层要求的第4.2.3.6节。(此资源只能用英文提供)
如果由于保持活动而导致连接丢失,则错误代码 WSAENETRESET将返回到套接字上正在进行的任何调用,并且随后的任何调用将随WSAENOTCONN失败。
如果对具有SO_KEEPALIVE的TCP套接字启用了保持活动,则默认TCP设置用于保持活动超时和间隔,除非通过使用SIO_KEEPALIVE_VALS选项调用WSAIoctl函数 来更改这些值。
SO_LINGER
SO_LINGER选项控制未连接的数据在套接字上排队并执行closesocket时所采取的 操作。见 字关闭了,其中的SO_LINGER设置影响语义的方式描述 关闭套接字。应用程序通过创建LERER结构(由optval参数指向)来设置所需的行为 ,这些成员使用这些成员l_onoff和l_linger进行适当的设置。
SO_REUSEADDR
默认情况下,不能绑定一个套接字(请参阅 bind)到已经在使用的本地地址。然而,有时,可能需要以这种方式重用地址。由于每个连接都由本地和远程地址的组合唯一标识,所以只要远程地址不同,就将两个套接字绑定到相同的本地地址就没有问题。要通知Windows Sockets提供程序,因为所需的地址已被另一个套接字使用,应该不会禁止套接字上的 绑定,所以应用程序应该在发布绑定之前为套接字设置SO_REUSEADDR套接字选项 。该选项仅在绑定时解释 。 在不绑定到现有地址的套接字上设置该选项是不必要和无害的。绑定后设置或重置该选项对此或任何其他套接字没有影响。
SO_RCVBUF和SO_SNDBUF
当Windows Sockets实现支持SO_RCVBUF和SO_SNDBUF选项时,应用程序可以请求不同的缓冲区大小(更大或更小)。即使实施没有提供所请求的总额,对setsockopt的调用 也可以成功。应用程序必须使用相同的选项调用 getsockopt来检查实际提供的缓冲区大小。
SO_RCVTIMEO和SO_SNDTIMEO
当使用 recv功能时,如果在SO_RCVTIMEO指定的时间段内没有数据到达,则 recv功能完成。在Windows 2000之前的Windows版本中,随后使用WSAETIMEDOUT,接收到的任何数据都将失败。在Windows 2000及更高版本中,如果在SO_RCVTIMEO 指定的时间内没有数据到达,则 recv函数返回WSAETIMEDOUT,如果接收到数据,则 recv返回SUCCESS。
如果发送或接收操作在套接字上超时,套接字状态是不确定的,不应该使用; 在这种状态下的TCP插座有可能导致数据丢失,因为操作可以在操作完成的同一时间被取消。
PVD_CONFIG
此对象存储与s参数中指定的套接字相关联的服务提供商的配置信息。这种数据结构的确切格式是每个服务提供商所特有的。
TCP_NODELAY
TCP_NODELAY选项特定于TCP / IP服务提供商。如果启用TCP_NODELAY选项(反之亦然),Nagle算法将被禁用。该过程涉及当有未确认的数据已经在飞行中或缓冲发送数据时缓冲发送数据,直到可以发送全尺寸数据包。强烈建议TCP / IP服务提供商默认启用Nagle算法,对于绝大多数应用协议,Nagle算法可以提供显着的性能增强。但是,对于某些应用程序,该算法可能会阻碍性能,TCP_NODELAY可用于将其关闭。这些是发送许多小消息的应用程序,并且维护消息之间的时间延迟。
注意 当发出阻止Winsock调用(如 setsockopt)时,Winsock可能需要等待网络事件才能完成调用。在这种情况下,Winsock会执行一个可警告的等待,这可以通过在同一线程上安排的异步过程调用(APC)中断。在APC中发出另一个阻塞Winsock调用,该过程会在同一个线程上中断正在进行的阻塞Winsock调用,这将导致未定义的行为,绝对不能由Winsock客户端尝试。
示例代码
以下示例演示了setsockopt函数。
C ++
#ifndef UNICODE
#define UNICODE
#endif
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <
winsock2.h>
#include < Ws2tcpip.h> #include <stdio.h> //链接ws2_32.lib
#pragma comment(lib,“Ws2_32.lib”)int main()
{ // ------------------------------------- - //声明变量
WSADATA wsaData;
SOCKET ListenSocket;
sockaddr_in服务; int iResult = 0;
BOOL bOptVal = FALSE; int bOptLen = sizeof(BOOL); int iOptVal = 0;
int iOptLen = sizeof(int); // --------------------------------------- //初始化Winsock
iResult = WSAStartup(MAKEWORD (2,2),&wsaData); if(iResult!= NO_ERROR){
wprintf(L “Error at WSAStartup()\ n”);
返回 1;
} // --------------------------------------- //创建一个监听套接字
ListenSocket =套接字(AF_INET,SOCK_STREAM,IPPROTO_TCP); if(ListenSocket == INVALID_SOCKET){
wprintf(L “socket function failed with error:%u \ n”,WSAGetLastError());
WSACleanup(); 返回 1;
} // --------------------------------------- //将套接字绑定到本地IP地址//和端口27015
hostent * thisHost; char * ip;
u_short端口
端口= 27015;
thisHost = gethostbyname(“”);
ip = inet_ntoa(*(struct in_addr *)* thisHost-> h_addr_list);
service.sin_family = AF_INET;
service.sin_addr.s_addr = inet_addr(ip);
service.sin_port = htons(port);
iResult = bind(ListenSocket,(SOCKADDR *)&service,sizeof(service));
if(iResult == SOCKET_ERROR){
wprintf(L “bind failed with error%u \ n”,WSAGetLastError());
关闭套接字(ListenSocket);
WSACleanup(); 返回 1;
} // --------------------------------------- //初始化变量并调用setsockopt。// SO_KEEPALIVE参数是一个套接字选项//使套接字在会话上发送keepalive消息//。SO_KEEPALIVE套接字选项//需要将一个布尔值传递给// setsockopt函数。如果为TRUE,则套接字//配置为发送keepalive消息,如果FALSE //套接字配置为不发送keepalive消息。//这段代码通过使用getsockopt函数检查套接字上的SO_KEEPALIVE的状态来测试setsockopt函数// 。
bOptVal = TRUE;
iResult = getsockopt(ListenSocket,SOL_SOCKET,SO_KEEPALIVE,(char *)&iOptVal,&iOptLen);
if(iResult == SOCKET_ERROR){
wprintf(L “getsockopt for SO_KEEPALIVE failed with error:%u \ n”,WSAGetLastError());
} else
wprintf(L “SO_KEEPALIVE Value:%ld \ n”,iOptVal);
iResult = setsockopt(ListenSocket,SOL_SOCKET,SO_KEEPALIVE,(char *)&bOptVal,bOptLen);
if(iResult == SOCKET_ERROR){
wprintf(L “setsockopt for SO_KEEPALIVE failed with error:%u \ n”,WSAGetLastError());
} else
wprintf(L “Set SO_KEEPALIVE:ON \ n”);
iResult = getsockopt(ListenSocket,SOL_SOCKET,SO_KEEPALIVE,(char *)&iOptVal,&iOptLen);
if(iResult == SOCKET_ERROR){
wprintf(L “getsockopt for SO_KEEPALIVE failed with error:%u \ n”,WSAGetLastError());
} else
wprintf(L “SO_KEEPALIVE Value:%ld \ n”,iOptVal);
关闭套接字(ListenSocket);
WSACleanup(); 返回 0;
}
IrDA插座注意事项
在使用IrDA的Windows套接字开发应用程序时,请注意以下事项:
- 必须明确地包含Af_irda.h头文件。
- IrDA提供以下套接字选项:
值 | 类型 | 含义 |
IRLMP_IAS_SET | * IAS_SET | 设置IAS属性 |
IRLMP_IAS_SET套接字选项使应用程序可以在本地IAS中设置单个类的单个属性。应用程序指定要设置的类,属性和属性类型。应用程序预期为传递的参数分配必要大小的缓冲区。
IrDA提供了一个存储基于IrDA的信息的IAS数据库。通过Windows Sockets 2接口可以访问对IAS数据库的访问,但这种访问通常不被应用程序使用,并且主要用于支持与不符合Windows Sockets 2 IrDA约定的非Windows设备的连接。
以下结构IAS_SET与IRLMP_IAS_SET setsockopt选项一起用于管理本地IAS数据库:
C ++
// #include <Af_irda.h>为此struct
typedef struct _IAS_SET {
u_char irdaClassName [IAS_MAX_CLASSNAME]; char irdaAttribName [IAS_MAX_ATTRIBNAME];
u_long irdaAttribType; 工会
{
LONG irdaAttribInt; struct
{
u_long Len;
u_char OctetSeq [IAS_MAX_OCTET_STRING];
irdaAttribOctetSeq; struct
{
u_long Len;
u_long CharSet;
u_char UsrStr [IAS_MAX_USER_STRING];
irdaAttribUsrStr;
irdaAttribute;
以下结构IAS_QUERY与IRLMP_IAS_QUERY setsockopt选项一起用于查询对等体的IAS数据库:
C ++
// #include <Af_irda.h>为此struct
typedef struct _WINDOWS_IAS_QUERY {
u_char irdaDeviceID [4]; char irdaClassName [IAS_MAX_CLASSNAME];
char irdaAttribName [IAS_MAX_ATTRIBNAME];
u_long irdaAttribType; 工会
{
LONG irdaAttribInt; struct
{
u_long Len;
u_char OctetSeq [IAS_MAX_OCTET_STRING];
irdaAttribOctetSeq; struct
{
u_long Len;
u_long CharSet;
u_char UsrStr [IAS_MAX_USER_STRING];
irdaAttribUsrStr;
irdaAttribute;
} IAS_QUERY,* PIAS_QUERY,FAR * LPIASQUERY;
许多SO_级套接字选项对IrDA无效。只有SO_LINGER被特别支持。
Windows Phone 8: Windows Phone 8及更高版本上的Windows Phone Store应用程序支持此功能。
Windows 8.1和Windows Server 2012 R2:Windows 8.1,Windows Server 2012 R2和更高版本上的Windows Store应用程序支持此功能。
要求
最低支持客户端 | Windows 8.1,Windows Vista [桌面应用程序| Windows Store应用程序] |
最低支持服务器 | Windows Server 2003 [桌面应用程序| Windows Store应用程序] |
最低支持的手机 | Windows Phone 8 |
头 | Winsock2.h |
图书馆 | WS2_32.LIB |
DLL | WS2_32.DLL |
也可以看看
捆绑
插座
套接字选项
错误代码 | 含义 |
在使用此功能之前,必须发生成功的 WSAStartup调用。 | |
网络子系统失败。 | |
optval参数指向的缓冲区不在进程地址空间的有效部分或 optlen参数太小。 | |
正在进行阻止Windows Sockets 1.1呼叫,或者服务提供商仍在处理回调函数。 | |
的电平的参数是无效的,或者在缓冲器中的信息指向的optval的参数是无效的。 | |
设置SO_KEEPALIVE时,连接已超时。 | |
该选项对于指定的提供程序或套接字是未知的或不受支持的(请参阅SO_GROUP_PRIORITY限制)。 | |
SO_KEEPALIVE设置后,连接已被重置。 | |
描述符不是套接字。 |
备注
备注
的 setsockopt的函数设置用于与任何类型的插座,在任何状态相关联的套接字选项的当前值。虽然选项可以存在于多个协议级别,但它们始终位于最上层的套接字级别。选项影响套接字操作,例如在正常数据流中是否接收到加急数据(例如,OOB数据),以及是否可以在套接字上发送广播消息。
注意: 如果 setsockopt的功能是之前调用 绑定功能,TCP / IP选项将不会被直到使用TCP / IP检查 结合进行。在这种情况下, setsockopt函数调用将始终成功,但由于早期的 setsockopt调用失败, 绑定函数调用可能会 失败。
注意 如果一个套接字被打开,将进行一个 setsockopt调用,然后进行一个 sendto调用,Windows Sockets执行一个隐式的 绑定函数调用。
有两种类型的套接字选项:启用或禁用特性或行为的布尔选项,以及需要整数值或结构的选项。要启用布尔选项,optval参数指向非零整数。要禁用选项optval指向等于零的整数。对于布尔选项,optlen参数应该等于sizeof(int)
。对于其他选项,optval指向包含该选项所需值的整数或结构,optlen是整数或结构的长度。
下表列出了setsockopt函数支持的一些常用选项。“类型”列标识由optval参数寻址的数据类型。“说明”列提供了有关套接字选项的一些基本信息。有关套接字选项和更详细信息(例如默认值)的更完整列表,请参阅“ 套接字选项”下的详细主题。
level = SOL_SOCKET
值 | 类型 | 描述 |
SO_BROADCAST | BOOL | 配置发送广播数据的套接字。 |
SO_CONDITIONAL_ACCEPT | BOOL | 允许传入连接被应用程序接受或拒绝,而不是协议栈。 |
SO_DEBUG | BOOL | 启用调试输出。Microsoft提供商目前不输出任何调试信息。 |
SO_DONTLINGER | BOOL | 不阻止关闭等待未发送的数据。设置此选项等同于将l_onoff设置为零时设置SO_LINGER 。 |
SO_DONTROUTE | BOOL | 设置传出数据是否应在套接字绑定的接口上发送,而不是在某个其他接口上发送。ATM套接字不支持此选项(导致错误)。 |
SO_GROUP_PRIORITY | INT | 保留。 |
BOOL | 允许为套接字连接发送保持活动数据包。ATM套接字不支持(导致错误)。 | |
SO_LINGER | 萦绕 | 如果不存在数据,则关闭。 |
SO_OOBINLINE | BOOL | 表示外部数据应与常规数据一致返回。此选项仅适用于支持带外数据的面向连接的协议。有关此主题的讨论,请参阅无 协议独立的带外数据。 |
SO_RCVBUF | INT | 指定保留接收的每个套接字缓冲区总数。 |
SO_REUSEADDR | BOOL | 允许套接字绑定到已经在使用的地址。有关更多信息,请参阅 绑定。不适用于ATM插座。 |
BOOL | 使套接字被绑定以进行独占访问。不需要管理权限。 | |
SO_RCVTIMEO | DWORD | 设置阻止接收呼叫的超时(以毫秒为单位)。 |
SO_SNDBUF | INT | 指定为发送预留的每个套接字缓冲区总数。 |
SO_SNDTIMEO | DWORD | 阻塞发送呼叫的超时(以毫秒为单位)。 |
SO_UPDATE_ACCEPT_CONTEXT | INT | 使用监听套接字的上下文更新接受套接字。 |
PVD_CONFIG | 服务提供者依赖 | 此对象存储与套接字s关联的服务提供商的配置信息。该数据结构的确切格式是特定于服务提供商。 |
有关level = SOL_SOCKET的套接字选项的更完整和详细的信息,请参阅SOL_SOCKET套接字选项。
level = IPPROTO_TCP
值 | 类型 | 描述 |
TCP_NODELAY | BOOL | 此套接字选项包括与Windows Sockets 1.1的向后兼容性 |
有关level = IPPROTO_TCP的套接字选项的更完整和详细的信息,请参阅IPPROTO_TCP套接字选项。
level = NSPROTO_IPX
值 | 类型 | 描述 |
IPX_PTYPE | INT | 设置IPX包类型。 |
IPX_FILTERPTYPE | INT | 设置接收过滤器包类型 |
IPX_STOPFILTERPTYPE | INT | 停止过滤使用IPX_FILTERTYPE设置的过滤器类型 |
IPX_DSTYPE | INT | 在发送的每个数据包上设置SPX头中数据流字段的值。 |
IPX_EXTENDED_ADDRESS | BOOL | 设置是否启用扩展寻址。 |
IPX_RECVHDR | BOOL | 设置协议头是否在所有接收头上发送。 |
IPX_RECEIVE_BROADCAST | BOOL | 表示广播报文很可能在套接字上。默认设置为TRUE。不使用广播的应用程序应将其设置为FALSE以获得更好的系统性能。 |
IPX_IMMEDIATESPXACK | BOOL | 指示SPX连接在发送ACK之前不会延迟。没有来回流量的应用程序应将此设置为TRUE,以提高性能。 |
有关level = NSPROTO_IPX的套接字选项的更完整和详细的信息,请参阅NSPROTO_IPX套接字选项。
setsockopt不支持的BSD选项 如下表所示。
值 | 类型 | 描述 |
SO_ACCEPTCONN | BOOL | 返回套接字是否处于侦听模式。此选项仅适用于面向连接的协议。该套接字选项不支持该设置。 |
SO_RCVLOWAT | INT | 包括BSD UNIX的套接字选项,用于向后兼容。此选项设置套接字输入操作要处理的最小字节数。 |
SO_SNDLOWAT | INT | 包括BSD UNIX的套接字选项,用于向后兼容。此选项设置套接字输出操作要处理的最小字节数。 |
SO_TYPE | INT | 返回给定套接字的套接字类型(SOCK_STREAM或SOCK_DGRAM,例如套接字类型的设置不支持此套接字选项。 |
SO_CONDITIONAL_ACCEPT
将此套接字选项设置为TRUE会延迟连接的确认,直到调用WSAAccept条件函数为止 。如果为FALSE,则在调用条件功能之前可以接受连接,但如果条件功能拒绝该呼叫,则连接将被断开。在调用listen函数之前必须设置此选项 ,否则返回WSAEINVAL。SO_CONDITIONAL_ACCEPT仅支持TCP和ATM。
默认情况下,TCP将SO_CONDITIONAL_ACCEPT设置为FALSE,因此默认情况下,将在WSAAccept条件函数被调用之前接受连接 。当设置为TRUE时,必须在TCP连接超时之内进行条件决定。CF_DEFER连接仍然会超时。
默认情况下,ATM将SO_CONDITIONAL_ACCEPT设置为TRUE。
SO_DEBUG
如果应用程序设置了SO_DEBUG选项,Windows Sockets服务提供商将被鼓励(但不是必需)提供输出调试信息。用于生成调试信息及其形式的机制超出了本文档的范围。
SO_GROUP_PRIORITY
保留以备将来使用套接字组。组优先级表示指定套接字相对于套接字组内其他套接字的相对优先级。值是非负整数,零对应于最高优先级。优先级值代表底层服务提供商关于如何分配潜在稀缺资源的提示。例如,当两个或更多个套接字都准备好传输数据时,最高优先级套接字(SO_GROUP_PRIORITY的最低值)应首先进行处理,其余的根据其相对优先级依次进行服务。
应用程序可以通过打开SO_KEEPALIVE套接字选项来请求TCP / IP提供商启用TCP连接上的保持活动数据包。Windows Sockets提供程序不需要支持使用keep-alives。如果是这样,精确的语义是实现特定的,但应符合关于IETF网站上提供的RFC 1122中规定的Internet主机 - 通信层要求的第4.2.3.6节。(此资源只能用英文提供)
如果由于保持活动而导致连接丢失,则错误代码 WSAENETRESET将返回到套接字上正在进行的任何调用,并且随后的任何调用将随WSAENOTCONN失败。
如果对具有SO_KEEPALIVE的TCP套接字启用了保持活动,则默认TCP设置用于保持活动超时和间隔,除非通过使用SIO_KEEPALIVE_VALS选项调用WSAIoctl函数 来更改这些值。
SO_LINGER
SO_LINGER选项控制未连接的数据在套接字上排队并执行closesocket时所采取的 操作。见 字关闭了,其中的SO_LINGER设置影响语义的方式描述 关闭套接字。应用程序通过创建LERER结构(由optval参数指向)来设置所需的行为 ,这些成员使用这些成员l_onoff和l_linger进行适当的设置。
SO_REUSEADDR
默认情况下,不能绑定一个套接字(请参阅 bind)到已经在使用的本地地址。然而,有时,可能需要以这种方式重用地址。由于每个连接都由本地和远程地址的组合唯一标识,所以只要远程地址不同,就将两个套接字绑定到相同的本地地址就没有问题。要通知Windows Sockets提供程序,因为所需的地址已被另一个套接字使用,应该不会禁止套接字上的 绑定,所以应用程序应该在发布绑定之前为套接字设置SO_REUSEADDR套接字选项 。该选项仅在绑定时解释 。 在不绑定到现有地址的套接字上设置该选项是不必要和无害的。绑定后设置或重置该选项对此或任何其他套接字没有影响。
SO_RCVBUF和SO_SNDBUF
当Windows Sockets实现支持SO_RCVBUF和SO_SNDBUF选项时,应用程序可以请求不同的缓冲区大小(更大或更小)。即使实施没有提供所请求的总额,对setsockopt的调用 也可以成功。应用程序必须使用相同的选项调用 getsockopt来检查实际提供的缓冲区大小。
SO_RCVTIMEO和SO_SNDTIMEO
当使用 recv功能时,如果在SO_RCVTIMEO指定的时间段内没有数据到达,则 recv功能完成。在Windows 2000之前的Windows版本中,随后使用WSAETIMEDOUT,接收到的任何数据都将失败。在Windows 2000及更高版本中,如果在SO_RCVTIMEO 指定的时间内没有数据到达,则 recv函数返回WSAETIMEDOUT,如果接收到数据,则 recv返回SUCCESS。
如果发送或接收操作在套接字上超时,套接字状态是不确定的,不应该使用; 在这种状态下的TCP插座有可能导致数据丢失,因为操作可以在操作完成的同一时间被取消。
PVD_CONFIG
此对象存储与s参数中指定的套接字相关联的服务提供商的配置信息。这种数据结构的确切格式是每个服务提供商所特有的。
TCP_NODELAY
TCP_NODELAY选项特定于TCP / IP服务提供商。如果启用TCP_NODELAY选项(反之亦然),Nagle算法将被禁用。该过程涉及当有未确认的数据已经在飞行中或缓冲发送数据时缓冲发送数据,直到可以发送全尺寸数据包。强烈建议TCP / IP服务提供商默认启用Nagle算法,对于绝大多数应用协议,Nagle算法可以提供显着的性能增强。但是,对于某些应用程序,该算法可能会阻碍性能,TCP_NODELAY可用于将其关闭。这些是发送许多小消息的应用程序,并且维护消息之间的时间延迟。
注意 当发出阻止Winsock调用(如 setsockopt)时,Winsock可能需要等待网络事件才能完成调用。在这种情况下,Winsock会执行一个可警告的等待,这可以通过在同一线程上安排的异步过程调用(APC)中断。在APC中发出另一个阻塞Winsock调用,该过程会在同一个线程上中断正在进行的阻塞Winsock调用,这将导致未定义的行为,绝对不能由Winsock客户端尝试。
示例代码
以下示例演示了setsockopt函数。
C ++
#ifndef UNICODE
#define UNICODE
#endif
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <
winsock2.h>
#include < Ws2tcpip.h> #include <stdio.h> //链接ws2_32.lib
#pragma comment(lib,“Ws2_32.lib”)int main()
{ // ------------------------------------- - //声明变量
WSADATA wsaData;
SOCKET ListenSocket;
sockaddr_in服务; int iResult = 0;
BOOL bOptVal = FALSE; int bOptLen = sizeof(BOOL); int iOptVal = 0;
int iOptLen = sizeof(int); // --------------------------------------- //初始化Winsock
iResult = WSAStartup(MAKEWORD (2,2),&wsaData); if(iResult!= NO_ERROR){
wprintf(L “Error at WSAStartup()\ n”);
返回 1;
} // --------------------------------------- //创建一个监听套接字
ListenSocket =套接字(AF_INET,SOCK_STREAM,IPPROTO_TCP); if(ListenSocket == INVALID_SOCKET){
wprintf(L “socket function failed with error:%u \ n”,WSAGetLastError());
WSACleanup(); 返回 1;
} // --------------------------------------- //将套接字绑定到本地IP地址//和端口27015
hostent * thisHost; char * ip;
u_short端口
端口= 27015;
thisHost = gethostbyname(“”);
ip = inet_ntoa(*(struct in_addr *)* thisHost-> h_addr_list);
service.sin_family = AF_INET;
service.sin_addr.s_addr = inet_addr(ip);
service.sin_port = htons(port);
iResult = bind(ListenSocket,(SOCKADDR *)&service,sizeof(service));
if(iResult == SOCKET_ERROR){
wprintf(L “bind failed with error%u \ n”,WSAGetLastError());
关闭套接字(ListenSocket);
WSACleanup(); 返回 1;
} // --------------------------------------- //初始化变量并调用setsockopt。// SO_KEEPALIVE参数是一个套接字选项//使套接字在会话上发送keepalive消息//。SO_KEEPALIVE套接字选项//需要将一个布尔值传递给// setsockopt函数。如果为TRUE,则套接字//配置为发送keepalive消息,如果FALSE //套接字配置为不发送keepalive消息。//这段代码通过使用getsockopt函数检查套接字上的SO_KEEPALIVE的状态来测试setsockopt函数// 。
bOptVal = TRUE;
iResult = getsockopt(ListenSocket,SOL_SOCKET,SO_KEEPALIVE,(char *)&iOptVal,&iOptLen);
if(iResult == SOCKET_ERROR){
wprintf(L “getsockopt for SO_KEEPALIVE failed with error:%u \ n”,WSAGetLastError());
} else
wprintf(L “SO_KEEPALIVE Value:%ld \ n”,iOptVal);
iResult = setsockopt(ListenSocket,SOL_SOCKET,SO_KEEPALIVE,(char *)&bOptVal,bOptLen);
if(iResult == SOCKET_ERROR){
wprintf(L “setsockopt for SO_KEEPALIVE failed with error:%u \ n”,WSAGetLastError());
} else
wprintf(L “Set SO_KEEPALIVE:ON \ n”);
iResult = getsockopt(ListenSocket,SOL_SOCKET,SO_KEEPALIVE,(char *)&iOptVal,&iOptLen);
if(iResult == SOCKET_ERROR){
wprintf(L “getsockopt for SO_KEEPALIVE failed with error:%u \ n”,WSAGetLastError());
} else
wprintf(L “SO_KEEPALIVE Value:%ld \ n”,iOptVal);
关闭套接字(ListenSocket);
WSACleanup(); 返回 0;
}
IrDA插座注意事项
在使用IrDA的Windows套接字开发应用程序时,请注意以下事项:
- 必须明确地包含Af_irda.h头文件。
- IrDA提供以下套接字选项:
值 | 类型 | 含义 |
IRLMP_IAS_SET | * IAS_SET | 设置IAS属性 |
IRLMP_IAS_SET套接字选项使应用程序可以在本地IAS中设置单个类的单个属性。应用程序指定要设置的类,属性和属性类型。应用程序预期为传递的参数分配必要大小的缓冲区。
IrDA提供了一个存储基于IrDA的信息的IAS数据库。通过Windows Sockets 2接口可以访问对IAS数据库的访问,但这种访问通常不被应用程序使用,并且主要用于支持与不符合Windows Sockets 2 IrDA约定的非Windows设备的连接。
以下结构IAS_SET与IRLMP_IAS_SET setsockopt选项一起用于管理本地IAS数据库:
C ++
// #include <Af_irda.h>为此struct
typedef struct _IAS_SET {
u_char irdaClassName [IAS_MAX_CLASSNAME]; char irdaAttribName [IAS_MAX_ATTRIBNAME];
u_long irdaAttribType; 工会
{
LONG irdaAttribInt; struct
{
u_long Len;
u_char OctetSeq [IAS_MAX_OCTET_STRING];
irdaAttribOctetSeq; struct
{
u_long Len;
u_long CharSet;
u_char UsrStr [IAS_MAX_USER_STRING];
irdaAttribUsrStr;
irdaAttribute;
以下结构IAS_QUERY与IRLMP_IAS_QUERY setsockopt选项一起用于查询对等体的IAS数据库:
C ++
// #include <Af_irda.h>为此struct
typedef struct _WINDOWS_IAS_QUERY {
u_char irdaDeviceID [4]; char irdaClassName [IAS_MAX_CLASSNAME];
char irdaAttribName [IAS_MAX_ATTRIBNAME];
u_long irdaAttribType; 工会
{
LONG irdaAttribInt; struct
{
u_long Len;
u_char OctetSeq [IAS_MAX_OCTET_STRING];
irdaAttribOctetSeq; struct
{
u_long Len;
u_long CharSet;
u_char UsrStr [IAS_MAX_USER_STRING];
irdaAttribUsrStr;
irdaAttribute;
} IAS_QUERY,* PIAS_QUERY,FAR * LPIASQUERY;
许多SO_级套接字选项对IrDA无效。只有SO_LINGER被特别支持。
Windows Phone 8: Windows Phone 8及更高版本上的Windows Phone Store应用程序支持此功能。
Windows 8.1和Windows Server 2012 R2:Windows 8.1,Windows Server 2012 R2和更高版本上的Windows Store应用程序支持此功能。
要求
最低支持客户端 | Windows 8.1,Windows Vista [桌面应用程序| Windows Store应用程序] |
最低支持服务器 | Windows Server 2003 [桌面应用程序| Windows Store应用程序] |
最低支持的手机 | Windows Phone 8 |
头 | Winsock2.h |
图书馆 | WS2_32.LIB |
DLL | WS2_32.DLL |
标签:02,选项,UDP,--,TCP,Windows,SO,接字,IAS From: https://blog.51cto.com/u_15872025/5845483