IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> 网络编程学习(六) -> 正文阅读

[网络协议]网络编程学习(六)

网络编程学习(六)

WinSock编程

函数	描述
accept	允许在套接字上进行传入连接尝试。
AcceptEx	接受新连接,返回本地和远程地址,并接收客户端应用程序发送的第一个数据块。
bind	将本地地址与套接字关联。
closesocket	关闭现有套接字。
connect	建立与指定套接字的连接。
ConnectEx	建立与指定套接字的连接,并可选择在建立连接后发送数据。 仅在面向连接的套接字上受支持。
DisconnectEx	关闭套接字上的连接,并允许重用套接字句柄。
EnumProtocols	检索有关在本地主机上处于活动状态的指定网络协议集的信息。
freeaddrinfo	检索有关在本地主机上处于活动状态的指定网络协议集的信息
FreeAddrInfoEx	释放GetAddrInfoEx函数在addrinfoex结构中动态分配的地址信息。
FreeAddrInfoW	释放GetAddrInfoW函数在addrinfoW结构中动态分配的地址信息。
gai_strerror	根据getaddrinfo函数返回的EAI_ *错误,帮助打印错误消息。
GetAcceptExSockaddrs	解析从调用AcceptEx函数获得的数据。
GetAddressByName	查询命名空间或一组默认命名空间,以检索指定网络服务的网络地址信息。 此过程称为服务名称解析。 网络服务还可以使用该函数来获取可以与绑定功能一起使用的本地地址信息。
getaddrinfo	提供从ANSI主机名到地址的协议无关转换。
GetAddrInfoEx	提供与协议无关的名称解析以及其他参数,以限定哪些名称空间提供程序应处理请求。
GetAddrInfoExCancel	通过GetAddrInfoExfunction取消异步操作。
GetAddrInfoExOverlappedResult	获取GetAddrInfoEx函数的异步操作使用的OVERLAPPED结构的返回码。
GetAddrInfoW	提供从Unicode主机名到地址的独立于协议的转换。
gethostbyaddr	检索与网络地址对应的主机信息。
gethostbyname	从主机数据库中检索与主机名对应的主机信息。 不推荐使用:改用getaddrinfo。
gethostname	检索本地计算机的标准主机名。
GetHostNameW	以Unicode字符串形式检索本地计算机的标准主机名。
getipv4sourcefilter	检索IPv4套接字的多播过滤器状态。
GetNameByType	检索指定服务类型的网络服务的名称。
getnameinfo	提供从IPv4或IPv6地址到ANSI主机名的名称解析,以及从端口号到ANSI服务名称的名称解析。
GetNameInfoW	提供从IPv4或IPv6地址到Unicode主机名以及从端口号到Unicode服务名称的名称解析。
getpeername	检索套接字连接的对等体的地址。
getprotobyname	检索与协议名称对应的协议信息。
getprotobynumber	检索与协议号对应的协议信息。
getservbyname	检索与服务名称和协议对应的服务信息。
getservbyport	检索与端口和协议对应的服务信息。
GetService	在一组默认命名空间或指定命名空间的上下文中检索有关网络服务的信息。
getsockname	检索套接字的本地名称。
getsockopt	检索套接字选项。
getsourcefilter	检索IPv4或IPv6套接字的多播过滤器状态。
GetTypeByName	检索由name指定的网络服务的服务类型GUID。
htond	将double从主机转换为TCP / IP网络字节顺序(这是big-endian)。
htonf	将浮动从主机转换为TCP / IP网络字节顺序(这是big-endian)。
htonl	将u_long从主机转换为TCP / IP网络字节顺序(这是big-endian)。
htonll	将无符号__int64从主机转换为TCP / IP网络字节顺序(这是big-endian)。
htons	将u_short从主机转换为TCP / IP网络字节顺序(这是big-endian)。
inet_addr	将包含(Ipv4)Internet协议虚线地址的字符串转换为in_addr结构的正确地址。
inet_ntoa	将(IPv4)Internet网络地址转换为Internet标准点分格式的字符串。
InetNtop	将IPv4或IPv6 Internet网络地址转换为Internet标准格式的字符串。 此函数的ANSI版本是inet_ntop。
InetPton	将标准文本表示形式的IPv4或IPv6 Internet网络地址转换为其数字二进制形式。 此函数的ANSI版本为inet_pton。
ioctlsocket	控制套接字的I / O模式。
listen	将套接字置于正在侦听传入连接的状态。
ntohd	将无符号__int64从TCP / IP网络顺序转换为主机字节顺序(在Intel处理器上为little-endian)并返回double。
ntohf	将无符号__int32从TCP / IP网络顺序转换为主机字节顺序(在Intel处理器上为little-endian)并返回浮点数。
ntohl	将u_long从TCP / IP网络顺序转换为主机字节顺序(在Intel处理器上为little-endian)。
ntohll	将无符号__int64从TCP / IP网络顺序转换为主机字节顺序(在Intel处理器上为little-endian)。
ntohs	将u_short从TCP / IP网络字节顺序转换为主机字节顺序(在Intel处理器上为little-endian)。
recv	从连接或绑定的套接字接收数据。
recvfrom	接收数据报并存储源地址。
RIOCloseCompletionQueue	通过使用Winsock注册的I / O扩展发送和接收请求,关闭用于I / O完成通知的现有完成队列。
RIOCreateCompletionQueue	创建特定大小的I / O完成队列,以便与Winsock注册的I / O扩展一起使用。
RIOCreateRequestQueue	使用指定的套接字和I / O完成队列创建已注册的I / O套接字描述符,以便与Winsock注册的I / O扩展一起使用。
RIODequeueCompletion	从I / O完成队列中删除条目以与Winsock注册的I / O扩展一起使用。
RIODeregisterBuffer	取消注册与Winsock注册的I / O扩展一起使用的注册缓冲区。
RIONotify	使用I / O完成队列注册用于通知行为的方法,以便与Winsock注册的I / O扩展一起使用。
RIOReceive	在连接的已注册I / O TCP套接字或绑定的已注册I / O UDP套接字上接收网络数据,以便与Winsock注册的I / O扩展一起使用。
RIOReceiveEx	接收已连接的已注册I / O TCP套接字或绑定的已注册I / O UDP套接字上的网络数据,以及用于Winsock注册的I / O扩展的其他选项。
RIORegisterBuffer	使用指定的缓冲区注册RIO_BUFFERID(已注册的缓冲区描述符),以便与Winsock注册的I / O扩展一起使用。
RIOResizeCompletionQueue	将I / O完成队列的大小调整为更大或更小,以便与Winsock注册的I / O扩展一起使用。
RIOResizeRequestQueue	将请求队列的大小调整为更大或更小,以便与Winsock注册的I / O扩展一起使用。
RIOSend	在连接的已注册I / O TCP套接字或绑定的已注册I / O UDP套接字上发送网络数据,以便与Winsock注册的I / O扩展一起使用。
RIOSendEx	在连接的已注册I / O TCP套接字或绑定的已注册I / O UDP套接字上发送网络数据,以及用于Winsock注册的I / O扩展的其他选项。
select	确定一个或多个套接字的状态,必要时等待执行同步I / O.
send	在连接的套接字上发送数据。
sendto	将数据发送到特定目的地。
SetAddrInfoEx	使用特定命名空间提供程序注册主机和服务名称以及关联的地址。
setipv4sourcefilter	设置IPv4套接字的多播过滤器状态。
SetService	在注册表中注册或删除一个或多个名称空间内的网络服务。 还可以在一个或多个名称空间中添加或删除网络服务类型。
SetSocketMediaStreamingMode	指示网络是否用于传输需要服务质量的流媒体。
setsockopt	设置套接字选项。
setsourcefilter	设置IPv4或IPv6套接字的多播过滤器状态。
shutdown	禁用套接字上的发送或接收。
socket	创建绑定到特定服务提供者的套接字。
TransmitFile	通过连接的套接字句柄传输文件数据。
TransmitPackets	通过连接的套接字传输内存数据或文件数据。
WSAAccept	有条件地接受基于条件函数的返回值的连接,提供服务质量流规范,并允许传输连接数据。
WSAAddressToString	将sockaddr结构的所有组件转换为地址的人类可读字符串表示形式。
WSAAsyncGetHostByAddr	异步检索与地址对应的主机信息。
WSAAsyncGetHostByName	异步检索与主机名对应的主机信息。
WSAAsyncGetProtoByName	异步检索与协议名称对应的协议信息。
WSAAsyncGetProtoByNumber	异步检索与协议号对应的协议信息。
WSAAsyncGetServByName	异步检索与服务名称和端口对应的服务信息。
WSAAsyncGetServByPort	异步检索与端口和协议对应的服务信息。
WSAAsyncSelect	请求基于Windows消息的基于消息的网络事件通知。
WSACancelAsyncRequest	取消不完整的异步操作。
WSACleanup	终止使用Ws2_32.DLL。
WSACloseEvent	关闭一个打开的事件对象句柄。
WSAConnect	建立与另一个套接字应用程序的连接,交换连接数据,并根据指定的FLOWSPEC结构指定所需的服务质量。
WSAConnectByList	建立与一组目标地址(主机名和端口)所代表的可能端点集合中的一个的连接。
WSAConnectByName	在指定的主机和端口上建立与另一个套接字应用程序的连接
WSACreateEvent	创建一个新的事件对象。
WSADeleteSocketPeerTargetName	删除对等目标名称与套接字IP地址之间的关联。
WSADuplicateSocket	返回可用于为共享套接字创建新套接字描述符的结构。
WSAEnumNameSpaceProviders	检索有关可用命名空间的信息。
WSAEnumNameSpaceProvidersEx	检索有关可用命名空间的信息。
WSAEnumNetworkEvents	发现指示套接字的网络事件的发生,清除内部网络事件记录和重置事件对象(可选)。
WSAEnumProtocols	检索有关可用传输协议的信息。
WSAEventSelect	指定与指定的FD_XXX网络事件集关联的事件对象。
__WSAFDIsSet	指定套接字是否包含在一组套接字描述符中。
WSAGetLastError	返回上次失败操作的错误状态。
WSAGetOverlappedResult	检索指定套接字上的重叠操作的结果。
WSAGetQOSByName	基于命名模板初始化QOS结构,或者它提供缓冲区以检索可用模板名称的枚举。
WSAGetServiceClassInfo	从指定的命名空间提供程序检索与指定服务类有关的类信息(模式)。
WSAGetServiceClassNameByClassId	检索与指定类型关联的服务的名称。
WSAHtonl	将u_long从主机字节顺序转换为网络字节顺序。
WSAHtons	将u_short从主机字节顺序转换为网络字节顺序。
WSAImpersonateSocketPeer	用于模拟与套接字对等体对应的安全主体,以便执行应用程序级授权。
WSAInstallServiceClass	在命名空间内注册服务类模式。
WSAIoctl	控制套接字的模式。
WSAJoinLeaf	将叶节点连接到多点会话,交换连接数据,并根据指定的结构指定所需的服务质量。
WSALookupServiceBegin	启动受WSAQUERYSET结构中包含的信息约束的客户端查询。
WSALookupServiceEnd	释放先前调用WSALookupServiceBegin和WSALookupServiceNext所使用的句柄。
WSALookupServiceNext	检索所请求的服务信息。
WSANSPIoctl	开发人员对已注册的命名空间进行I / O控制调用。
WSANtohl	将u_long从网络字节顺序转换为主机字节顺序。
WSANtohs	将u_short从网络字节顺序转换为主机字节顺序。
WSAPoll	确定一个或多个套接字的状态。
WSAProviderConfigChange	更改提供程序配置时通知应用程序。
WSAQuerySocketSecurity	查询有关应用于套接字连接的安全性的信息。
WSARecv	从连接的套接字接收数据。
WSARecvDisconnect	终止套接字上的接收,并在套接字面向连接时检索断开连接数据。
WSARecvEx	从连接的套接字接收数据。
WSARecvFrom	接收数据报并存储源地址。
WSARecvMsg	从连接和未连接的套接字接收数据和可选控制信息。
WSARemoveServiceClass	从注册表中永久删除服务类架构。
WSAResetEvent	将指定事件对象的状态重置为无信号。
WSARevertImpersonation	终止套接字对等体的模拟。
WSASend	在连接的套接字上发送数据。在连接的套接字上发送数据。
WSASendDisconnect	启动套接字连接的终止并发送断开连接数据。
WSASendMsg	从连接和未连接的套接字发送数据和可选控制信息。
WSASendTo	使用重叠的I / O将数据发送到特定目标。
WSASetEvent	设置要发信号的指定事件对象的状态。
WSASetLastError	设置错误代码。
WSASetService	在注册表中注册或删除一个或多个名称空间中的服务实例。
WSASetSocketPeerTargetName	用于指定与对等IP地址对应的对等目标名称(SPN)。 此目标名称应由客户端应用程序指定,以安全地标识应进行身份验证的对等方。
WSASetSocketSecurity	启用并应用套接字的安全性。
WSASocket	创建绑定到特定传输服务提供程序的套接字。
WSAStartup	通过进程启动WS2_32.DLL的使用。
WSAStringToAddress	将数字字符串转换为sockaddr结构。
WSAWaitForMultipleEvents	当一个或所有指定的事件对象处于信号状态或超时间隔到期时返回。
https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-accept

WinSock的注册与注销

1、初始化函数WSAStartup()

int WSAAPI WSAStartup( WORD [指定应用程序所要使用的WinSock规范的最高版本,主版本号在低字节,辅版本号在高字节] wVersionRequested, LPWSADATA lpWSAData[指向WSADATA结构变量的指针,用来返回WinSockAPI实现的字节信息] );

typedef struct WSAData {
WORD wVersion;
WORD wHighVersion;
#ifdef _WIN64
unsigned short iMaxSockets;
unsigned short iMaxUdpDg;
char FAR * lpVendorInfo;
char szDescription[WSADESCRIPTION_LEN+1];
char szSystemStatus[WSASYS_STATUS_LEN+1];
#else
char szDescription[WSADESCRIPTION_LEN+1];
char szSystemStatus[WSASYS_STATUS_LEN+1];
unsigned short iMaxSockets;
unsigned short iMaxUdpDg;
char FAR * lpVendorInfo;
#endif
} WSADATA;

WSADATA结构被用来保存AfxSocketInit函数返回的WindowsSockets初始化信息。
wVersion

Windows Sockets DLL期望调用者使用的Windows Sockets规范的版本。 高位字节存储副版本号, 低位字节存储主版本号,可以用WORD MAKEWORD(BYTE,BYTE ) 返回这个值,例如:MAKEWORD(1,1)

wHighVersion

这个DLL能够支持的Windows Sockets规范的最高版本。通常它与wVersion相同。

szDescription

以null结尾的ASCII字符串,Windows Sockets DLL将对Windows Sockets实现的描述拷贝到这个字符串中,包括制造商标识。文本(最多可以有256个字符)可以包含任何字符,但是要注意不能包含控制字符和格式字符,应用程序对其最可能的使用方式是把它(可能被截断)显示在在状态信息中。

szSystemStatus

以null结尾的ASCII字符串,Windows Sockets DLL把有关的状态或配置信息拷贝到该字符串中。Windows Sockets DLL应当仅在这些信息对用户或支持人员有用时才使用它们,它不应被作为szDescription域的扩展。

iMaxSockets

单个进程能够打开的socket的最大数目。Windows Sockets的实现能提供一个全局的socket池,可以为任何进程分配;或者它也可以为socket分配属于进程的资源。这个数字能够很好地反映Windows Sockets DLL或网络软件的配置方式。应用程序的编写者可以通过这个数字来粗略地指明Windows Sockets的实现方式对应用程序是否有用。例如,X Windows服务器在第一次启动的时候可能会检查iMaxSockets的值:如果这个值小于8,应用程序将显示一条错误信息,指示用户重新配置网络软件(这是一种可能要使用szSystemStatus文本的场合)。显然无法保证某个应用程序能够真正分配iMaxSockets个socket,因为可能有其它WindowsSockets应用程序正在使用。

iMaxUdpDg

Windows Sockets应用程序能够发送或接收的最大的用户数据包协议(UDP)的数据包大小,以字节为单位。如果实现方式没有限制,那么iMaxUdpDg为零。在Berkeley sockets的许多实现中,对于UDP数据包有个固有的限制(在必要时被分解),大小为8192字节。Windows Sockets的实现可以对碎片重组缓冲区的分配作出限制。对于适合的WindowsSockets 实现,iMaxUdpDg的最小值为512。注意不管iMaxUdpDg的值是什么,都不推荐你发回一个比网络的最大传送单元(MTU)还大的广播数据包。(Windows Sockets API 没有提供发现MTU的机制,但是它不会小于512个字节)。WinSock2.0版中已被废弃。

lpVendorInfo

指向销售商的数据结构的指针。这个结构的定义(如果有)超出了WindowsSockets规范的范围。WinSock2.0版中已被废弃。
初始化函数可能返回的错误代码:

WSASYSNOTREADY :网络通信依赖的子网系统没有准备好

WSAVERNOTSUPPORTED:找不到所需的WinSock API相应的动态链接库

WSAEINVAL:DLL不支持应用程序所需的WinSock版本

WSAEINPROGRESS:正在执行一个阻塞的WinSock1.1操作

WSAEPROCLIM:已经到达WinSock支持的任务数上线

WSAEFAULT:参数lpWSAData不是合法指针

2、注销函数WSACleanup()

当程序使用完WinSock。dll提供的服务后,应用程序必须调用WSACleanup(),来解除WinSock.dll库的绑定,释放WinSock实现分配给应用程序的系统资源,终止Windows Sockets DLL的使用

可能返回的错误代码

WSANOTINITIALISED:使用本函数前必须有一次成功的WSAStartup调用

WSAENETDOWN:Windows Socket的实现已经检测到网络子系统故障

WSAEINPROGRESS:一个阻塞的Windows Sockets操作正在运行

Socket函数

int socket(int domain, int type, int protocol);

socket函数对应于普通文件的打开操作。普通文件的打开操作返回一个文件描述字,而**socket()**用于创建一个socket描述符(socket descriptor),它唯一标识一个socket。这个socket描述字跟文件描述字一样,后续的操作都有用到它,把它作为参数,通过它来进行一些读写操作。

正如可以给fopen的传入不同参数值,以打开不同的文件。创建socket的时候,也可以指定不同的参数创建不同的socket描述符,socket函数的三个参数分别为:

  • domain:即协议域,又称为协议族(family)。常用的协议族有,AF_INET、AF_INET6、AF_LOCAL(或称AF_UNIX,Unix域socket)、AF_ROUTE等等。协议族决定了socket的地址类型,在通信中必须采用对应的地址,如AF_INET决定了要用ipv4地址(32位的)与端口号(16位的)的组合、AF_UNIX决定了要用一个绝对路径名作为地址。
  • type:指定socket类型。常用的socket类型有,SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等等(socket的类型有哪些?)。
  • protocol:故名思意,就是指定协议。常用的协议有,IPPROTO_TCP、IPPTOTO_UDP、IPPROTO_SCTP、IPPROTO_TIPC等,它们分别对应TCP传输协议、UDP传输协议、STCP传输协议、TIPC传输协议(这个协议我将会单独开篇讨论!)。

注意:并不是上面的type和protocol可以随意组合的,如SOCK_STREAM不可以跟IPPROTO_UDP组合。当protocol为0时,会自动选择type类型对应的默认协议。

当我们调用socket创建一个socket时,返回的socket描述字它存在于协议族(address family,AF_XXX)空间中,但没有一个具体的地址。如果想要给它赋值一个地址,就必须调用bind()函数,否则就当调用connect()、listen()时系统会自动随机分配一个端口。

WSAEAFNOSUPPORT:不支持所指定的通信域或地址簇

WSAEMFILE:没有可用的套接字描述符,说明创建的套接字已超出限额

WSAENOBUFS:没有可用的缓冲区,无法创建套接字

WSAEPROTONOSUPPORT:不支持指定的协议

WSAEPROTOTYPE:指定的协议类型不适用于本套接口

WSAEDOCKTNOSUPPORT:本地址簇中不支持该类型的套接字

bind()函数

正如上面所说bind()函数把一个地址族中的特定地址赋给socket。例如对应AF_INET、AF_INET6就是把一个ipv4或ipv6地址和端口号组合赋给socket。

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

函数的三个参数分别为:

  • sockfd:即socket描述字,它是通过socket()函数创建了,唯一标识一个socket。bind()函数就是将给这个描述字绑定一个名字。

  • addr:一个

    const

    struct

    sockaddr *指针,指向要绑定给sockfd的协议地址。这个地址结构根据地址创建socket时的地址协议族的不同而不同,如ipv4对应的是:

    struct sockaddr_in {
        sa_family_t    sin_family; /* address family: AF_INET */
        in_port_t      sin_port;   /* port in network byte order */
        struct in_addr sin_addr;   /* internet address */
    };
    
    /* Internet address. */
    struct in_addr {
        uint32_t       s_addr;     /* address in network byte order */
    };
    

    ipv6对应的是:

    struct sockaddr_in6 { 
        sa_family_t     sin6_family;   /* AF_INET6 */ 
        in_port_t       sin6_port;     /* port number */ 
        uint32_t        sin6_flowinfo; /* IPv6 flow information */ 
        struct in6_addr sin6_addr;     /* IPv6 address */ 
        uint32_t        sin6_scope_id; /* Scope ID (new in 2.4) */ 
    };
    
    struct in6_addr { 
        unsigned char   s6_addr[16];   /* IPv6 address */ 
    };
    

    Unix域对应的是:

    #define UNIX_PATH_MAX    108
    
    struct sockaddr_un { 
        sa_family_t sun_family;               /* AF_UNIX */ 
        char        sun_path[UNIX_PATH_MAX];  /* pathname */ 
    };
    
  • addrlen:对应的是地址的长度。

通常服务器在启动的时候都会绑定一个众所周知的地址(如ip地址+端口号),用于提供服务,客户就可以通过它来接连服务器;而客户端就不用指定,有系统自动分配一个端口号和自身的ip地址组合。这就是为什么通常服务器端在listen之前会调用bind(),而客户端就不会调用,而是在connect()时由系统随机生成一个。

网络字节序与主机字节序

****主机字节序****就是我们平常说的大端和小端模式:不同的CPU有不同的字节序类型,这些字节序是指整数在内存中保存的顺序,这个叫做主机序。引用标准的Big-Endian和Little-Endian的定义如下:

a) Little-Endian就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。

b) Big-Endian就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。

****网络字节序****:4个字节的32 bit值以下面的次序传输:首先是0~7bit,其次8~15bit,然后16~23bit,最后是24~31bit。这种传输次序称作大端字节序。**由于TCP/IP首部中所有的二进制整数在网络中传输时都要求以这种次序,因此它又称作网络字节序。**字节序,顾名思义字节的顺序,就是大于一个字节类型的数据在内存中的存放顺序,一个字节的数据没有顺序的问题了。

所以:在将一个地址绑定到socket的时候,请先将主机字节序转换成为网络字节序,而不要假定主机字节序跟网络字节序一样使用的是Big-Endian。由于这个问题曾引发过血案!公司项目代码中由于存在这个问题,导致了很多莫名其妙的问题,所以请谨记对主机字节序不要做任何假定,务必将其转化为网络字节序再赋给socket。

WSAEAFNOSUPPORT:不支持所指定的通信域或地址簇。

WSAEADDRINUSE:指定了已经在使用中的端口,造成冲突

WSAEFAULT:入口参数错误,namelen参数太小,小于sockaddrdr结构的大小

WSAEINVAL:该套接字已经与一个网络地址绑定。

WSAENOBUFS:没有可用的缓冲区,连接过多

WSAENOTSOCK:描述字不是一个套接字

如果作为一个服务器,在调用socket()、bind()之后就会调用listen()来监听这个socket,如果客户端这时调用connect()发出连接请求,服务器端就会接收到这个请求。

int listen(int sockfd, int backlog);
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

listen函数的第一个参数即为要监听的socket描述字,第二个参数为相应socket可以排队的最大连接个数。socket()函数创建的socket默认是一个主动类型的,listen函数将socket变为被动类型的,等待客户的连接请求。

listen仅适用于支持连接的套接字,在Internet通信域,仅用于流式套接字,并且仅用于服务端,监听套接字必须绑定到特定的网络地址上

connect函数的第一个参数即为客户端的socket描述字,第二参数为服务器的socket地址,第三个参数为socket地址的长度。客户端通过调用connect函数来建立与TCP服务器的连接。

connect用于客户机请求与服务器建立连接

connect可能返回的错误代码

WSAEADDRINUSE:所指的地址已在使用中

WSAEINTR:通过WSACancelBlockingCall()来取消一个阻塞的调用

WSAEADDRNOTAVAIL:找不到所指的网络地址

WSAENOTSUPPORT:所指族中地址无法与本套接字一起使用

WSAECONNREFUSED:尝试连接被强行拒绝

WSAEDESTADDREQ:需要目的地地址

WSAWFAULT:namelen参数不正确

WSAEINVAL:套接口没有准备好与一地址捆绑

WSAEISCONN:套接口早已连接

WSAEMFILE:无多余文件描述字

WSAENETUNREACH:当前无法从主机访问网络

WSAENOBUFS:无可用缓冲区,套接口未被连接

WSAENOTSOCK:描述字不是一个套接口

WSAETIMEOUT:超时时间到

WSAEWOULDBLOCK:套接口被设置为非阻塞方式且连接不能立即建立

listen可能返回的错误代码

WSAEADDRINUSE:试图监听一个正在使用中的地址

WSAEINVAL:该套接字未用bind()进行绑定,或者已经被链接

WSAEISCONN:套接口已被连接

WSAEMFILE:无可用文件描述字

WSAENOBUFS:无可用缓冲区空间

WSAENOTSOCK:描述字不是一个套接口

WSAEOPNOTSUPP:该套接口不正常listen()调用

TCP服务器端依次调用socket()、bind()、listen()之后,就会监听指定的socket地址了。TCP客户端依次调用socket()、connect()之后就想TCP服务器发送了一个连接请求。TCP服务器监听到这个请求之后,就会调用accept()函数取接收请求,这样连接就建立好了。之后就可以开始网络I/O操作了,即类同于普通文件的读写I/O操作。

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

accept函数的第一个参数为服务器的socket描述字,第二个参数为指向struct sockaddr *的指针,用于返回客户端的协议地址,第三个参数为协议地址的长度。如果accpet成功,那么其返回值是由内核自动生成的一个全新的描述字,代表与返回客户的TCP连接。

注意:accept的第一个参数为服务器的socket描述字,是服务器开始调用socket()函数生成的,称为监听socket描述字;而accept函数返回的是已连接的socket描述字。一个服务器通常通常仅仅只创建一个监听socket描述字,它在该服务器的生命周期内一直存在。内核为每个由服务器进程接受的客户连接创建了一个已连接socket描述字,当服务器完成了对某个客户的服务,相应的已连接socket描述字就被关闭。

万事具备只欠东风,至此服务器与客户已经建立好连接了。可以调用网络I/O进行读写操作了,即实现了网咯中不同进程之间的通信!网络I/O操作有下面几组:

  • read()/write()
  • recv()/send()
  • readv()/writev()
  • recvmsg()/sendmsg()
  • recvfrom()/sendto()

我推荐使用recvmsg()/sendmsg()函数,这两个函数是最通用的I/O函数,实际上可以把上面的其它函数都替换成这两个函数。它们的声明如下:

       #include <unistd.h>       ssize_t read(int fd, void *buf, size_t count);       ssize_t write(int fd, const void *buf, size_t count);       #include <sys/types.h>       #include <sys/socket.h>       ssize_t send(int sockfd, const void *buf, size_t len, int flags);       ssize_t recv(int sockfd, void *buf, size_t len, int flags);       ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,                      const struct sockaddr *dest_addr, socklen_t addrlen);       ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,                        struct sockaddr *src_addr, socklen_t *addrlen);       ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);       ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);

read函数是负责从fd中读取内容.当读成功时,read返回实际所读的字节数,如果返回的值是0表示已经读到文件的结束了,小于0表示出现了错误。如果错误为EINTR说明读是由中断引起的,如果是ECONNREST表示网络连接出了问题。

write函数将buf中的nbytes字节内容写入文件描述符fd.成功时返回写的字节数。失败时返回-1,并设置errno变量。 在网络程序中,当我们向套接字文件描述符写时有俩种可能。1)write的返回值大于0,表示写了部分或者是全部的数据。2)返回的值小于0,此时出现了错误。我们要根据错误类型来处理。如果错误为EINTR表示在写的时候出现了中断错误。如果为EPIPE表示网络连接出现了问题(对方已经关闭了连接)。

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-08-20 15:27:26  更:2021-08-20 15:28:10 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 20:17:32-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码