`

Windows Socket API 使用小结

阅读更多
一、WSAStartup函数
intWSAStartup(
WORDwVersionRequested,
LPWSADATAlpWSAData
);
使 用Socket的程序在使用Socket之前必须调用WSAStartup函数。该函数的第一个参数指明程序请求使用的Socket版本,其中高位字节指 明副版本、低位字节指明主版本;操作系统利用第二个参数返回请求的Socket的版本信息。当一个应用程序调用WSAStartup函数时,操作系统根据 请求的Socket版本来搜索相应的Socket库,然后绑定找到的Socket库到该应用程序中。以后应用程序就可以调用所请求的Socket库中的其 它Socket函数了。该函数执行成功后返回0。
例:假如一个程序要使用2.1版本的Socket,那么程序代码如下
wVersionRequested=MAKEWORD(2,1);
err=WSAStartup(wVersionRequested,&wsaData);

二、WSACleanup函数
intWSACleanup(void);
应用程序在完成对请求的Socket库的使用后,要调用WSACleanup函数来解除与Socket库的绑定并且释放Socket库所占用的系统资源。

三、socket函数
SOCKETsocket(
intaf,
inttype,
intprotocol
);
应 用程序调用socket函数来创建一个能够进行网络通信的套接字。第一个参数指定应用程序使用的通信协议的协议族,对于TCP/IP协议族,该参数置 PF_INET;第二个参数指定要创建的套接字类型,流套接字类型为SOCK_STREAM、数据报套接字类型为SOCK_DGRAM;第三个参数指定应 用程序所使用的通信协议。该函数如果调用成功就返回新创建的套接字的描述符,如果失败就返回INVALID_SOCKET。套接字描述符是一个整数类型的 值。每个进程的进程空间里都有一个套接字描述符表,该表中存放着套接字描述符和套接字数据结构的对应关系。该表中有一个字段存放新创建的套接字的描述符, 另一个字段存放套接字数据结构的地址,因此根据套接字描述符就可以找到其对应的套接字数据结构。每个进程在自己的进程空间里都有一个套接字描述符表但是套 接字数据结构都是在操作系统的内核缓冲里。下面是一个创建流套接字的例子:
structprotoent*ppe;
ppe=getprotobyname("tcp");
SOCKETListenSocket=socket(PF_INET,SOCK_STREAM,ppe->p_proto);

四、closesocket函数
intclosesocket(
SOCKETs
);
closesocket 函数用来关闭一个描述符为s套接字。由于每个进程中都有一个套接字描述符表,表中的每个套接字描述符都对应了一个位于操作系统缓冲区中的套接字数据结构, 因此有可能有几个套接字描述符指向同一个套接字数据结构。套接字数据结构中专门有一个字段存放该结构的被引用次数,即有多少个套接字描述符指向该结构。当 调用closesocket函数时,操作系统先检查套接字数据结构中的该字段的值,如果为1,就表明只有一个套接字描述符指向它,因此操作系统就先把s在 套接字描述符表中对应的那条表项清除,并且释放s对应的套接字数据结构;如果该字段大于1,那么操作系统仅仅清除s在套接字描述符表中的对应表项,并且把 s对应的套接字数据结构的引用次数减1。
closesocket函数如果执行成功就返回0,否则返回SOCKET_ERROR。

五、send函数
intsend(
SOCKETs,
constcharFAR*buf,
intlen,
intflags
);
不 论是客户还是服务器应用程序都用send函数来向TCP连接的另一端发送数据。客户程序一般用send函数向服务器发送请求,而服务器则通常用send函 数来向客户程序发送应答。该函数的第一个参数指定发送端套接字描述符;第二个参数指明一个存放应用程序要发送数据的缓冲区;第三个参数指明实际要发送的数 据的字节数;第四个参数一般置0。这里只描述同步Socket的send函数的执行流程。当调用该函数时,send先比较待发送数据的长度len和套接字 s的发送缓冲区的长度,如果len大于s的发送缓冲区的长度,该函数返回SOCKET_ERROR;如果len小于或者等于s的发送缓冲区的长度,那么 send先检查协议是否正在发送s的发送缓冲中的数据,如果是就等待协议把数据发送完,如果协议还没有开始发送s的发送缓冲中的数据或者s的发送缓冲中没 有数据,那么send就比较s的发送缓冲区的剩余空间和len,如果len大于剩余空间大小send就一直等待协议把s的发送缓冲中的数据发送完,如果 len小于剩余空间大小send就仅仅把buf中的数据copy到剩余空间里(注意并不是send把s的发送缓冲中的数据传到连接的另一端的,而是协议传 的,send仅仅是把buf中的数据copy到s的发送缓冲区的剩余空间里)。如果send函数copy数据成功,就返回实际copy的字节数,如果 send在copy数据时出现错误,那么send就返回SOCKET_ERROR;如果send在等待协议传送数据时网络断开的话,那么send函数也返 回SOCKET_ERROR。要注意send函数把buf中的数据成功copy到s的发送缓冲的剩余空间里后它就返回了,但是此时这些数据并不一定马上被 传到连接的另一端。如果协议在后续的传送过程中出现网络错误的话,那么下一个Socket函数就会返回SOCKET_ERROR。(每一个除send外的 Socket函数在执行的最开始总要先等待套接字的发送缓冲中的数据被协议传送完毕才能继续,如果在等待时出现网络错误,那么该Socket函数就返回 SOCKET_ERROR)
注意:在Unix系统下,如果send在等待协议传送数据时网络断开的话,调用send的进程会接收到一个SIGPIPE信号,进程对该信号的默认处理是进程终止。

六、recv函数
intrecv(
SOCKETs,
charFAR*buf,
intlen,
intflags
);
不 论是客户还是服务器应用程序都用recv函数从TCP连接的另一端接收数据。该函数的第一个参数指定接收端套接字描述符;第二个参数指明一个缓冲区,该缓 冲区用来存放recv函数接收到的数据;第三个参数指明buf的长度;第四个参数一般置0。这里只描述同步Socket的recv函数的执行流程。当应用 程序调用recv函数时,recv先等待s的发送缓冲中的数据被协议传送完毕,如果协议在传送s的发送缓冲中的数据时出现网络错误,那么recv函数返回 SOCKET_ERROR,如果s的发送缓冲中没有数据或者数据被协议成功发送完毕后,recv先检查套接字s的接收缓冲区,如果s接收缓冲区中没有数据 或者协议正在接收数据,那么recv就一直等待,只到协议把数据接收完毕。当协议把数据接收完毕,recv函数就把s的接收缓冲中的数据copy到buf 中(注意协议接收到的数据可能大于buf的长度,所以在这种情况下要调用几次recv函数才能把s的接收缓冲中的数据copy完。recv函数仅仅是 copy数据,真正的接收数据是协议来完成的),recv函数返回其实际copy的字节数。如果recv在copy时出错,那么它返回 SOCKET_ERROR;如果recv函数在等待协议接收数据时网络中断了,那么它返回0。
注意:在Unix系统下,如果recv函数在等待协议接收数据时网络断开了,那么调用recv的进程会接收到一个SIGPIPE信号,进程对该信号的默认处理是进程终止。

七、bind函数
intbind(
SOCKETs,
conststructsockaddrFAR*name,
intnamelen
);
当 创建了一个Socket以后,套接字数据结构中有一个默认的IP地址和默认的端口号。一个服务程序必须调用bind函数来给其绑定一个IP地址和一个特定 的端口号。客户程序一般不必调用bind函数来为其Socket绑定IP地址和断口号。该函数的第一个参数指定待绑定的Socket描述符;第二个参数指 定一个sockaddr结构,该结构是这样定义的:
structsockaddr{
u_shortsa_family;
charsa_data[14];
};
sa_family指定地址族,对于TCP/IP协议族的套接字,给其置AF_INET。当对TCP/IP协议族的套接字进行绑定时,我们通常使用另一个地址结构:
structsockaddr_in{
shortsin_family;
u_shortsin_port;
structin_addrsin_addr;
charsin_zero[8];
};
其 中sin_family置AF_INET;sin_port指明端口号;sin_addr结构体中只有一个唯一的字段s_addr,表示IP地址,该字段 是一个整数,一般用函数inet_addr()把字符串形式的IP地址转换成unsignedlong型的整数值后再置给s_addr。有的服务器是多 宿主机,至少有两个网卡,那么运行在这样的服务器上的服务程序在为其Socket绑定IP地址时可以把htonl(INADDR_ANY)置给 s_addr,这样做的好处是不论哪个网段上的客户程序都能与该服务程序通信;如果只给运行在多宿主机上的服务程序的Socket绑定一个固定的IP地 址,那么就只有与该IP地址处于同一个网段上的客户程序才能与该服务程序通信。我们用0来填充sin_zero数组,目的是让sockaddr_in结构 的大小与sockaddr结构的大小一致。下面是一个bind函数调用的例子:
structsockaddr_insaddr;
saddr.sin_family=AF_INET;
saddr.sin_port=htons(8888);
saddr.sin_addr.s_addr=htonl(INADDR_ANY);
bind(ListenSocket,(structsockaddr*)&saddr,sizeof(saddr));

八、listen函数
intlisten(SOCKETs,intbacklog);
服务程序可以调用listen函数使其流套接字s处于监听状态。处于监听状态的流套接字s将维护一个客户连接请求队列,该队列最多容纳backlog个客户连接请求。假如该函数执行成功,则返回0;如果执行失败,则返回SOCKET_ERROR。

九、accept函数
SOCKETaccept(
SOCKETs,
structsockaddrFAR*addr,
intFAR*addrlen
);
服 务程序调用accept函数从处于监听状态的流套接字s的客户连接请求队列中取出排在最前的一个客户请求,并且创建一个新的套接字来与客户套接字创建连接 通道,如果连接成功,就返回新创建的套接字的描述符,以后与客户套接字交换数据的是新创建的套接字;如果失败就返回INVALID_SOCKET。该函数 的第一个参数指定处于监听状态的流套接字;操作系统利用第二个参数来返回新创建的套接字的地址结构;操作系统利用第三个参数来返回新创建的套接字的地址结 构的长度。下面是一个调用accept的例子:
structsockaddr_inServerSocketAddr;
intaddrlen;
addrlen=sizeof(ServerSocketAddr);
ServerSocket=accept(ListenSocket,(structsockaddr*)&ServerSocketAddr,&addrlen);

十、connect函数
intconnect(
SOCKETs,
conststructsockaddrFAR*name,
intnamelen
);
客户程序调用connect函数来使客户Sockets与监听于name所指定的计算机的特定端口上的服务Socket进行连接。如果连接成功,connect返回0;如果失败则返回SOCKET_ERROR。下面是一个例子:
structsockaddr_indaddr;
memset((void*)&daddr,0,sizeof(daddr));
daddr.sin_family=AF_INET;
daddr.sin_port=htons(8888);
daddr.sin_addr.s_addr=inet_addr("133.197.22.4");
connect(ClientSocket,(structsockaddr*)&daddr,sizeof(daddr))
WindowsSockets规范包含了以下Berkeley风格的套接口例程:

*表示例程在应用于阻塞套接口时会阻塞。

accept()*响应联结请求,并且新建一个套接口。原来的套接口则返回监听状态。

bind()把一个本地的名字和一个无名的套接口捆绑起来。

closesocket()*把套接口从拥有对象参考表中取消。该函数只有在SO_LINGER被设置时才会阻塞。

connect()*初始化到一个指定套接口上的连接。

getpeername()得到连接在指定套接口上的对等通讯方的名字。

getsockname()得到指定套接口上当前的名字。

getsockopt()得到与指定套接口相关的属性选项。

htonl()把32位的数字从主机字节顺序转换到网络字节顺序。

htons()把16位的数字从主机字节顺序转换到网络字节顺序。

inet_addr()把一个Internet标准的"."记号地址转换成Internet地址数值。

inet_ntoa()把Internet地址数值转换成带"."的ASCII字符串。

ioctlsocket()为套接口提供控制。

listen()监听某一指定套接口上连接请求的到来。

ntohl()把32位数字从网络字节顺序转换为主机字节顺序。

ntons()把16位数字从网络字节顺序转换为主机字节顺序。

recv()*从一个已连接的套接口接收数据。

recvfrom()*从一个已连接的或未连接的套接口接收数据。

select()*执行同步I/O多路复用。

send()*从一已连接的套接口发送数据。

sendto()*从已连接或未连接的套接口发送数据。

setsockopt()设置与指定套接口相关的属性选项。

shutdown()关闭一部分全双工的连接。

socket()创建一个通讯端点并返回一个套接口。


分享到:
评论

相关推荐

    WindowsSocket2API

    总结,Windows Socket 2 API 是Windows平台进行网络编程的基础,它提供了丰富的函数和特性,使开发者能够灵活构建各种复杂的网络应用。不论是简单的文件传输,还是复杂的分布式系统,都可以借助Winsock API来实现。...

    基于windows下socket API的实现

    总结来说,Windows下的Socket API为开发者提供了丰富的功能,涵盖了从创建套接字到数据传输的整个网络通信过程。通过学习和实践,无论是初学者还是有一定经验的开发者,都能掌握Socket API的基本用法,从而在Windows...

    VC++ SOCKET API通讯实例源码.zip

    总结来说,这个"VC++ SOCKET API通讯实例源码"是学习MFC结合SOCKET API进行网络编程的一个实用资源。通过分析和运行这个实例,开发者可以深入理解SOCKET API的工作原理,以及如何在MFC环境下实现高效的网络通信功能...

    Socket API,CAsyncSocket,CSocket内幕及其用法.doc

    总结来说,Socket API提供基础的网络通信接口,而MFC的CAsyncSocket和CSocket类是对Socket API的封装,使开发者能更方便地在Windows环境下进行网络编程。CAsyncSocket适合异步非阻塞的高效率通信,而CSocket则更适合...

    No4.CS_Win32_socket连接.rar_Socket API_win32 socket

    总结来说,Win32 Socket API为Windows环境下的网络编程提供了一套强大的工具。通过理解并实践“CS_Win32_socket连接.rar”中的示例,开发者可以掌握Socket连接的基本流程,从而在自己的项目中实现高效的网络通信。...

    MFC API socket通讯源码

    总结来说,这个“MFC API socket通讯源码”实例提供了学习和理解网络编程基础的好机会,包括如何使用MFC封装的socket API创建服务器和客户端,以及如何进行数据的发送和接收。通过分析和理解这些源码,开发者可以更...

    Api函数编写的Socket客户端,有注释

    总结,这个项目为学习和理解Socket编程提供了一个实践平台,特别是对于使用API函数而不是封装好的库的场景。通过阅读和分析代码,开发者可以深入理解TCP连接的建立、数据传输和断开过程,以及如何在Windows环境下...

    Windows Socket 通信网络编程

    实现方式:所有的Socket 编程方式全部采用Windows API 函数调用,未采用封装好的C++ socket 类进行实现,适用于底层编程的参考和学习,采用多线程的方式实现并发处理,支持多个客户端同时访问服务端 适用范围和参考...

    windowsSocket

    总结起来,Windows Socket是C++开发网络应用的重要工具,提供了丰富的API供开发者使用。理解并熟练掌握Winsock的这些核心功能和错误处理,是构建可靠、高效的网络应用程序的关键。无论你是新手还是经验丰富的开发者...

    Windows Socket 模型

    总结,Windows Socket模型的选择和使用是网络编程中的重要环节。了解select和events模型的原理和优缺点,有助于开发者设计出更加高效、稳定的网络应用程序。在实际开发中,应结合项目需求,灵活选用合适的模型,以...

    VC 不使用MFC实现Socket API封装.rar

    总结来说,"VC 不使用MFC实现Socket API封装"是一个关于如何在Windows环境下编写自定义的网络通信程序的话题。这种方式让开发者能够更好地控制底层细节,提高代码的灵活性,同时避免了对MFC的依赖。日志类的添加则...

    Windows socket

    总结来说,"Windows socket"项目中的"RTUClient"是一个使用Winsock 2.0 API编写的简单客户端程序,可能涉及到TCP连接、Modbus RTU通信等技术,用于与远程服务器或设备进行数据交换。在实际的开发过程中,需要理解...

    精通Windows.API-函数、接口、编程实例.pdf

    2.1.3 Windows数据类型与Windows API 14 2.1.4 Windows中的数据结构 15 2.2 Windows API的功能分类 15 2.2.1 系统基本服务 15 2.2.2 系统管理 17 2.2.3 用户界面 17 2.2.4 图像和多媒体 20 2.2.5 ...

    10TCPClient (windows api socket)

    总结来说,这个话题覆盖了Windows程序设计中的一个重要部分——使用API函数创建TCP客户端。通过学习和实践这样的实例,开发者能够增强对网络编程的理解,为后续更复杂的网络应用开发打下坚实基础。

    一个windows开源socket 库

    总结来说,这个开源的Windows Socket库为C++开发者提供了一种简洁且实用的网络通信解决方案。它可能包含了各种方便的特性,如异常处理、连接管理和多线程支持,使得在Windows环境下进行Socket编程变得更加便捷。通过...

    基于Windows API的Socket程序开发技术研究

    总结起来,基于Windows API的Socket程序开发技术涉及到理解Socket的创建、配置、绑定和通信过程。广播通信则需要额外设置`SO_BROADCAST`选项,以便Socket能够发送和接收广播数据。通过服务端和客户端的示例代码,...

    WindowsAPI 中文详解

    总结来说,Windows API 是Windows平台开发的核心,涵盖了大量的功能和细节。深入理解和熟练使用Windows API,对于开发高效且功能强大的Windows应用程序至关重要。通过阅读提供的帮助文件,开发者可以更轻松地掌握...

    windows socket网络编程实验教程

    - **API设计**:不仅包含了类似Berkeley Socket风格的库函数,还提供了一组面向Windows环境的扩展库函数,以充分利用Windows的消息驱动机制。 - **兼容性**:为了确保应用程序能在不同的网络软件供应商提供的...

    简单明了的Windows Socket网路通讯

    总结来说,Windows Socket通信涉及多个关键步骤,包括初始化Winsock、创建Socket、连接/监听、数据传输和资源释放。VC6虽然已经是一个较旧的开发工具,但它仍然能够提供一个良好的环境来学习和实践这些概念。通过...

    Windows平台下Socket例程

    在Windows环境中,Socket API遵循Berkeley Sockets模型,这是Internet编程的主流标准。 **TCP(Transmission Control Protocol)Socket:** TCP是一种面向连接的、可靠的传输协议,保证了数据的有序性和无丢失性。...

Global site tag (gtag.js) - Google Analytics