当前位置:文档之家› Socket函数说明

Socket函数说明

Socket函数说明
Socket函数说明

第六章Socket函数说明

6.1 库函数综述

6.1.1 套接字函数

表6.1 Windows Sockets 1.1版本的Berkeley Sockets函数

accept() *

确认外来连接,并将它与一个立即建立的数据套接字联系起来。原始套接字返回到监听状态。

bind()

给未命名套接字赋一个本地名。

closesocket() *

从进程对象参考表中删去一个套接字,只有当SO_LINGER设置时才阻塞。

connect() *

在指定套接字上初始化连接。

getpeername()

获取与指定套接字连接的对等方的名字。

getsockname()

获取指定套接字的当前名字。

getsockopt()

获取与指定套接字相关的选项。

htonl()

将一个32位数从主机字节顺序转换为网络字节顺序。

htons()

将一个16位数从主机字节顺序转换为网络字节顺序。

inet_addr()

将一个用网际标准点分表示法表示的字符串地址转换成网际地址值。

inet_ntoa()

将一个网际地址值转换成一个用点分十进制表示法表示的字符串地址

ioctlsocket()

为套接字提供控制。

listen()

在指定套接字上监听外来连接。

ntohl()

将一个32位数从网络字节顺序转换为主机字节顺序。

ntohs()

将一个16位数从网络字节顺序转换为主机字节顺序。

recv() *

从一个连接的套接字上接收数据。

recvfrom() *

从一个连接或未连接的套接字上接收数据。

select() *

执行多路同步I/O。

send() *

给一个连接套接字发送数据。

sendto() *

给一个连接或未连接套接字发送数据。

setsockopt()

设置与指定套接字相关的选项。

shutdown()

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

socket()

建立一个通讯用的末端点,返回一个套接字。

* = 如果作用于阻塞套接字上,此例程可用阻塞。

这些函数根据功能的不同可以分为如下几类:

(1) 套接字函数。此类函数包括sockets(),bind(),getpeername(),getsockname()和closesocket(),它们主要完成创建,关闭套接字功能,以及对套接字命名与名字获取。

(2) 网络连接函数。此类函数包括listen(),accept(),connect()和shutdown(),它们完成网络连接(如虚电路)的建立与关闭。此类函数中有部分可阻塞。

(3) 数据传输函数。此类函数包括send(),recv(),sendto()和recvfrom(),它们完成网络数据的发送与接收,全部是可以阻塞的函数。

(4) 字节定序函数。此类函数包括htonl(),htons(),ntohl()和ntohs(),它们完成主机和网络之间数据字节顺序的转换。

(5) 地址转换函数。此类函数包括inet_addr(),inet_ntoa(),它们完成网络字符串地址和Internet地址之间的转换。

(6) 套接字控制函数。此类函数包括getsockopt(),setsockopt(),ioctlsocket()和select(),它们设置/获取套接字的选项,控制/检测套接字的工作状态。其中select()函数在必要时可能阻塞。

只使用了上述函数的Berkeley Sockets源程序基本上可以不加修改地移植到Windows Sockets环境中来。但是,移植过来的程序有一个最大的问题是“阻塞”。在Berkeley Sockets 中,套接字默认的工作模式是操作处于阻塞方式,一个阻塞操作可能阻塞整个Windows环境。在非抢先Windows环境,强烈推荐程序员使用非阻塞(异步)操作,也就是说,推荐使用Windows Sockets提供的异步选择函数代替可能阻塞的select()函数,并且用网络事件消息来驱动可能阻塞的网络连接函数(accept()和connect())和数据传输函数,这样设计的程序能更好地工作。

5.1.2 数据库函数

Windows Sockets定义了如表6.2所示的“数据库”函数:

表6.2 Windows Sockets 1.1版本定义的“数据库”函数

gethostbyaddr() *

通过网络地址获取主机名字和地址等信息。

gethostbyname() *

通过主机名字获取主机名字和地址等信息。

gethostname()

获取本地主机名。

getprotobyname() *

通过协议名获取协议名和协议号等信息。

getprotobynumber() *

通过协议号获取协议名和协议号等信息。

getservbyname() *

通过服务名获取服务的名字和端口等信息。

getservbyport() *

通过端口获取服务的名字和端口等信息。

* = 在某些条件下此例程可能阻塞。

提供这类函数是为了获取网络特定的信息,在最初的Berkeley版本中,它们是作为在文本数据库文件中寻找信息的机构。在Windows Sockets实现中,可能使用了不依赖于本地数据库文件的方法(如域名服务),但是对应用程序来说请求这些信息的格式是一致的,并且对应用程序来说是透明的。

调用这些例程所获得的信息存放在由Windows Sockets实现分配的一个结构中,函数返回此结构的地址。因此,应用程序可以通过此结构指针获取所需要的信息,但它决不能试图修改此结构,更不能释放结构的任一部分。另外,对一个线程来说,Windows Sockets实现只分配了结构的一个备份,任何Windows Sockets API调用都可能修改此结构。也就是说,结构指针指向的数据只在此线程的下一次Windows Sockets API调用之前才是正确的,应用程序应该在发布任何其它Windows Sockets API调用之前将任何需要的信息拷贝出来。

数据库函数除了gethostname()之外都是阻塞的,Windows Sockets提供它们是为了Berkeley Sockets网络程序的可移植性。在设计实现Windows Sockets应用程序时,推荐使用Windows Sockets提供的数据库函数的异步版本(见下节)。

6.2 标准Socket函数

6.2.1 accept()

语法:SOCKET WSAAPI

accept (

IN SOCKET s,

OUT struct sockaddr FAR* addr,

OUT int FAR* addrlen

);

此函数用于从套接字上接收一个连接。它提取挂在套接字s 上的连接队列中的第一个连接,创建一个和s有相同属性(包括使用函数WSAAsyncSelect()或WSAEventSelect()注册的异步事件,但不包括监听套接字的套接字组ID)的新数据套接字,并返回一个指向新套接字的句柄。如果连接队列上没有等待的连接,并且套接字没有标志为非阻塞,那么accept()阻塞调用直到出现一个连接。如果套接字标志为非阻塞,并且队列上没有等待的连接,那么accept()返回错误WSAEWOULDBLOCK。新创建的数据套接字不能用来接收更多的连接,它只能用于数据传输;原来的套接字仍然打开,处于监听连接状态。

参数

描述

s

这是一个套接字描述符,该套接字在用作accept()函数的参数前必须先调用过listen()函数,此时它正处于监听连接的状态。

addr

一个可选的指向缓冲区的指针,用来接收连接实体的地址,在通讯层使用。addr的确切格式由套接字创建时建立的地址族决定。

addrlen

一个可选的指向整数的指针,它调用时含有地址addr指向的空间的大小,返回时含有返回的地址的确切长度(字节数)。

返回值:如果没有错误发生,accept()返回一个SOCKET类型的值,表示接收到的套接字的描述符。否则返回值INVALID_SOCKET,错误码可通过调用WSAGetLastError()函数得到。

错误码:

WSANOTINITIALISED

未初始化Windows Sockets DLL,在使用此函数之前必须有一次成功的WSAStartup()函数调用。

WSAENETDOWN

Windows Sockets 实现检测到网络系统已经失败。

WSAEFAULT

参数addrlen太小(小于结构sockaddr的大小),或参数addr不是用户地址空间的合法部分。

WSAEINTR

此(阻塞)调用已被WSACancelBlockingCall()函数取消。

WSAEINPROGRESS

一个阻塞的Windows Sockets 操作正在进行。

WSAEINVAL

在accept()调用之前没有执行过listen()。

WSAEMFILE

accept()队列入口空,但没有文件描述符可用。即打开的文件描述符过多。

WSAENOBUFS

无缓冲区空间可用。

WSAENOTSOCK

描述符s不是套接字描述符。

WSAEOPNOTSUPP

s指向的套接字不是一种支持面向连接服务类型的套接字。

WSAEWOULDBLOCK

套接字标志为非阻塞,但现在没有接收到连接。

注释:该调用只能和基于连接的套接字类型如SOCK_STREAM一起使用。如果参数addr 和/或addrlen等于NULL,那么没有关于接收套接字的远程地址信息返回。

参见:bind(), connect(), listen(), select(), socket(), WSAAsyncSelect(), WSAAccept()。

6.2.2 bind()

语法:int WSAAPI

bind (

IN SOCKET s,

IN const struct sockaddr FAR* name,

IN int namelen );

此函数用于未连接的数据报或流套接字,它将一本地地址与套接字连接,即建立半相关。当一套接字用socket()创建后,它存在于一名字空间(地址族), 但它没有赋予名字。bind()通过将一本地名字赋予一未命名的套接字, 建立起套接字的本地连接(主机地址/端口号)。

参数

描述

指示未连接的数据报或流套接字的描述符。

name

赋给套接字的本地地址(名字)。结构sockaddr定义如下:

struct sockaddr {

u_short sa_family;

char sa_data[14];

};

除sa_family外,其它内容都以网络字节顺序表示。

namelen

地址缓冲区长度。

返回值:如果没有错误发生,bind()返回0。否则返回值SOCKET_ERROR,错误码可通过调用WSAGetLastError()函数得到。

错误码:

WSANOTINITIALISED

未初始化Windows Sockets DLL,在使用此函数之前必须有一次成功的WSAStartup()函数调用。

WSAENETDOWN

Windows Sockets 实现检测到网络系统已经失败。

WSAEADDRINUSE

指定的地址已经在使用(参见setsockopt()中的SO_REUSEADDR套接字选项)。

WSAEADDRNOTAVAIL

对于本机器来说,指定的地址是非法地址(WinSock 2)。

WSAEFAULT

参数namelen太小(小于结构sockaddr的长度);参数name或namelen不是用户地址空间

的合法部分;参数name包含了相关的地址族来说是不正确的地址格式;参数name指向的内存块的前两个字节与套接字描述符s相关的地址族不匹配。

WSAEINPROGRESS

一个阻塞的Windows Sockets 操作正在进行。

WSAEAFNOSUPPORT

此套接字不能使用指定地址族中的地址(WinSock 1.1)。

WSAEINVAL

此套接字已经捆扎到了一个地址。

WSAENOBUFS

无缓冲区空间可用,连接太多。

WSAENOTSOCK

此描述符不是套接字描述符。

注释:在Internet地址族中,一个名字有几个部分。对于SOCK_DGRAM和SOCK_STREAM 类型的套接字来说,名字分为三部分:主机地址,协议号(分别默认设置为UDP和TCP),以及一个标志应用程序的端口号。在WinSock 2中,参数name并不严格地解释为指向“sockaddr”结构的指针,但为了与Windows Sockets的兼容性仍用这种表示。服务提供者可以把它当作一个指向长度为namelen的内存块而自由处理,在此内存块的前两个字节(对应结构sockaddr定义中的sa_family元素)必须为包含建立套接字的地址族,否则将产生错误WSAEFAULT。

如果应用程序不关心赋予它的地址,则可指定一个等于常数INADDR_ANY的网际地址,和/或等于0的端口。如果网际地址等于INADDR_ANY,任何合适的网络接口都可用,这就简化了在多宿主机上的应用程序设计。当一个服务器向几个网络提供服务时,这将变得很重要。在不指定地址的情况下,服务器可以接收发向其端口的所有UDP数据包和TCP连接

请求,而不必关心请求是从哪一个网络接口到达的。如果端口指定为0,Windows Sockets 实现将为应用程序指定一界于1024和5000之间的端口值。应用程序可在bind()后使用getsockname()来得到赋给它的地址,但要注意的是,对于网际地址等于INADDR_ANY的情况,getsockname()只有当套接字连接后才填入网际地址(Internet address),原因是当主机是多

地址家族时,几个网际地址都是合法的。对客户应用程序来说,不鼓励将其绑扎到一个指定的端口,因为这样存在与已经使用了该端口的其它套接字冲突的危险。

由于Windows Sockets只支持AF_INET地址域,因此名字缓冲区的格式只能是sockaddr_in结构。此结构在winsock.h中定义如下:

struct in_addr

{

u_long s_addr;

};

struct sockaddr_in

{

u_char sin_len;

u_char sin_family;

u_short sin_port;

struct in_addr sin_addr;

char sin_zero[8];

};

·sin_family字段只能置为AF_INET。

·sin_port字段为应用程序必须连接的端口号。

·sin_addr字段为主机网际地址。

·sin_zero字段未用,留待以后扩充,必须全置为0。

注意,此结构的任何字段均为网络字节顺序。

在WinSock 2,支持的地址族得到扩展,因此结构sockaddr不只解释为sockaddr_in,根据不同的地址族,它有不同的确切格式。

参见:WSACancelBlockingCall(), connect(), listen(), getsockname(), setsockopt(), socket()。

6.2.3 closesocket()

语法:int WSAAPI

closesocket (

IN SOCKET s

);

此函数关闭套接字s,并释放分配给该套接字的资源,以后对s 的引用都将产生错误WSAENOTSOCK。如果s涉及一个打开的TCP连接,该连接被释放。

参数

描述

s

待关闭的套接字描述符。

返回值:如果没有错误发生,closesocket()返回0。否则返回值SOCKET_ERROR,错误码可通过调用WSAGetLastError()函数得到。

错误码:

WSANOTINITIALISED

未初始化Windows Sockets DLL,在使用此函数之前必须有一次成功的WSAStartup()函数调用。

WSAENETDOWN

Windows Sockets 实现检测到网络系统已经失败。

WSAENOTSOCK

此描述符不是套接字描述符。

WSAEINPROGRESS

一个阻塞的Windows Sockets 操作正在进行。

WSAEINTR

此(阻塞)调用已被WSACancelBlockingCall()函数取消。

WSAEWOULDBLOCK

套接字标志为非阻塞并且SO_LINGER设置为非零超时。

注释:closesocket()函数的语义受套接字选项SO_LINGER和SO_DONTLINGER的影响,具体见下表(默认情况下是允许SO_DONTLINGER):

选项

间隔

关闭类型

等待关闭?

SO_DONTLINGER

不用

Graceful

No

SO_LINGER

Hard

No

SO_LINGER

非零

Graceful

Yes

如果SO_LINGER设置(例如,linger结构的l_onoff域非零)并且超时间隔为零(l_linger 为零),那么即使队列数据尚未发送或确认,closesocket()函数也不会阻塞。这称作强制(“hard”或“abortive”)关闭,因为套接字的虚电路立即复位,任何未发送的数据都将丢失,并且在虚电路远程方的任何recv()调用都将以WSAECONNRESET失败。在这种情况下,套接字不进入TCP状态机的三次握手流程,系统资源被立即释放。这对于服务器应用程序非正常退出后希望能立即启动很有用,当正常通信中不鼓励使用。

如果SO_LINGER设置超时间隔为非零,closesocket()函数将阻塞,直到剩余的数据都发送完毕或直到超时退出,这称作“雅致”(graceful)关闭。注意如果套接字设置为非阻塞并且SO_LINGER设置为非零超时,调用closesocket()将失败,错误码为WSAEWOULDBLOCK。

如果SO_DONTLINGER设置在流套接字上(例如,linger结构的l_onoff域为零), closesocket()调用将立即返回。然而,排队等待传送的任何数据如果可能的话都将在该套接字关闭前发送出去,这也称作“雅致”关闭。注意在这些情况下,Windows Sockets实现可能会在任意时间内不释放套接字和其他资源, 这可能影响希望使用全部可用套接字的应用程序。如果应用程序要确保连接上的所有数据都被发送或接收到,则应该在调用closesocket()函数之前调用shutdown()函数。

下面给出closesocket()函数的小结:

·如果SO_DONTLINGER允许(默认设置),且不会出现错误WSAEWOULDBLOCK──连接在后台“雅致”关闭;

·如果SO_LINGER允许并且超时间隔为0,则总是立即返回──连接被重置或终止;

·如果SO_LINGER允许并且超时间隔非0:

──对于阻塞套接字,阻塞到所有数据发送完或超时间隔到时;

──对于非阻塞套接字,立即返回并且指示错误WSAEWOULDBLOCK。

参见:accept(), socket(), ioctisocket(), setsockopt(),WSAAsyncSelect(),WSADuplicateSocket()。

6.2.4 connect()

语法:int WSAAPI

connect (

IN SOCKET s,

IN const struct sockaddr FAR* name,

IN int namelen

);

此函数用来与对等方建立一个连接。如果套接字s没有绑扎,则系统赋予本地相关一个唯一值,并且套接字被表示为已绑扎的。

参数

描述

s

用来表示发出连接请求的套接字的描述符。

name

指向一个socket address结构的指针,该结构含有对等方的套接字的地址。

namelen

name指向的socket address结构的字节数。

返回值:如果没有错误发生,connect()返回0。否则返回值SOCKET_ERROR,错误码可通过调用WSAGetLastError()函数得到。

对于阻塞套接字来说,返回值表示连接试图是否成功。

对于非阻塞套接字来说,连接试图不一定马上完成。当connect()返回SOCKET_ERROR,并且WSAGetLastError()返回WSAEWOULDBLOCK时,应用程序可以:

1. 利用select()函数,通过检查套接字是否可写来判断连接请求是否完成。

2. 如果应用程序已使用WSAAsyncSelect()函数注册了对连接事件的兴趣,则当连接操作完成时应用程序将收到FD _CONNECT通知(无论成功与否)。

3. 如果应用程序已使用WSAEventSelect()函数注册了对连接事件的兴趣,则当连接操作完成时相应的事件对象将设置信号(无论成功与否)。

对于一个非阻塞套接字来说,在连接试图完成之前,任何对该套接字的connect()调用都将以错误码WSAEALREADY失败,在连接成功之后则返回错误码WSAEISCONN。由于Windows Sockets 1.1规范在定义当连接请求正在处理时调用connect()函数返回的错误值有二义性,其返回值对于不同的Windows Sockets实现其值不同,因此不推荐应用程序采用多次调用connect()函数的方式来检测连接是否完成。如果应用程序员一定要这么做,为了确保程序的可靠运行,他们在处理错误码WSAEALREADY的同时,还必须准备处理WSAEINVAL和WSAEWOULDBLOCK错误码。

如果返回值指出连接试图失败(例如WSAECONNREFUSED,WSAENETUNREACH,WSAETIMEDOUT等),则应用程序可对该套接字再次调用connect()函数。

错误码:

WSANOTINITIALISED

未初始化Windows Sockets DLL,在使用此函数之前必须有一次成功的WSAStartup()函数调用。

WSAENETDOWN

Windows Sockets 实现检测到网络系统已经失败。

WSAEADDRINUSE

套接字的本地地址已被使用,并且该套接字没有使用SO_REUSEADDR来设置允许地址重用。此错误经常发生在函数bind()调用时,但当bind()函数使用通配地址(包括ADDR_ANY)并且在connect()函数调用时需要“提交”一个指定地址时,此错误能够延迟到connect()函数。

WSAEINTR

阻塞的WinSock 1.1调用为WSACancelBlockingCall()函数撤消。

WSAEINPROGRESS

一个阻塞的Windows Sockets 1.1操作正在进行。

WSAEALREADY

一个非阻塞的connect()调用已经在指定的套接字上进行(WinSock 2)。

WSAEADDRNOTAVAIL

远程地址非法(如ADDR_ANY)。

WSAEAFNOSUPPORT

此套接字不能使用指定地址族中的地址。

WSAECONNREFUSED

连接请求被目的主机拒绝。

WSAEDESTADDRREQ

要求目标地址(WinSock 1.1)。

WSAEFAULT

参数name或namelen不是用户地址空间的合法部分;参数namelen太小(小于结构sockaddr 的长度);参数name包含了相关的地址族来说是不正确的地址格式。

WSAEINVAL

此套接字没有捆扎到一个地址,或套接字为监听套接字,或者指定的目的地址与套接字从属的强制组不一致。。

WSAEISCONN

此套接字已经建立了连接(只对面向连接的套接字有效)。

WSAEMFILE

无文件描述符可用(WinSock 1.1)。

WSAENETUNREACH

此主机现在不能到达网络。

WSAENOBUFS

无缓冲区空间可用,此套接字不能被连接。

WSAENOTSOCK

此描述符不是套接字描述符。

WSAETIMEDOUT

连接请求超时,未能建立连接。

WSAEWOULDBLOCK

套接字处于非阻塞模式,并且连接不能立即完成,它并不表明一个错误情况。

WSAEACCES

由于setsockopt()时未允许SO_BROADCAST,无法将一个数据报套接字与一个广播地址连接。

注释:客户程序在流套接字上调用connect()函数来建立与服务器的连接,服务器必须有一个空闲的被动接口。否则,connect()函数将以错误码WSAECONNREFUSED失败。

对于流套接字(类型SOCK_STREAM),connect()函数用来初始化与参数name(套接字名字空间中的地址)指示的外部主机的活动连接。当connect()调用成功完成后,套接字就可以收发数据了。如果结构name的地址域全为0,则返回错误WSAEADDRNOTAVAIL。

流套接字只能调用connect()函数一次,多次调用将以错误码WSAEISCONN失败。数据报套接字(类型SOCK_DGRAM)可以重复调用connect()函数来变换连接,它设置与数据报套接字数据传送的默认目标,供以后的send()/WSASend()和recv()/WSARecv()函数使用。数据报套接字可以通过连接一个无效地址,例如空地址(即全部字段清零)来结束连接。

对于无连接的套接字来说,name可以是任何合法的地址,包括广播地址。然而,要连接到一个广播地址,套接字必须使用setsockopt()函数的SO_BROADCAST选项来允许广播,否则connect()函数将以错误码WSAEACCES失败。

对于处于阻塞模式的套接字s,connect()函数阻塞调用者,直到建立起连接或有错误被接收到。对于非阻塞套接字s,如果返回值是SOCKET_ERROR,并且错误码为WSAEWOULDBLOCK,那么应用程序可以使用select()函数来检查套接字s是否可写来判定连接请求是否完成;如果应用程序使用了基于消息的WSAAsyncSelect()/WSAEventSelect()函数来指示感兴趣的连接事件,那么当连接操作完成后,应用程序将收到FD_CONNECT消息。

参见:accept(), bind(), getsockname(), socket(), select(), WSAAsyncSelect(), WSAConnect()。

6.2.5 getpeername()

语法:int WSAAPI

getpeername (

IN SOCKET s,

OUT struct sockaddr FAR* name,

IN OUT int FAR* namelen

);

此函数用来获取与套接字连接的对等方的地址,它检索与套接字s连接的对等方的名字,并把它存在sockaddr结构的name域中。此函数只能用于已连接的数据报或流套接字。对于数据报套接字,只有在先前的connect()调用中指定的对等方的名字被返回,而不会返回先前的sendto()调用指定的名字。

参数

描述

s

标识已连接的套接字的描述符。

name

指向连接的套接字网际地址的指针,该结构由getpeername()在返回之前填写,name的确切格式由通信发生的区域决定。

namelen

指向name所指结构大小的指针。它在返回时含有返回名字的实际字节数。

返回值:如果没有错误发生,getpeername()返回0。否则返回值SOCKET_ERROR,错误码可通过调用WSAGetLastError()函数得到。

错误码:

WSANOTINITIALISED

未初始化Windows Sockets DLL,在使用此函数之前必须有一次成功的WSAStartup()函数调用。

WSAENETDOWN

Windows Sockets 实现检测到网络系统已经失败。

WSAEFAULT

参数name或namelen不是用户地址空间的合法部分,或参数namelen不够大。

WSAEINPROGRESS

一个阻塞的Windows Sockets 操作正在进行。

WSAENOTCONN

套接字没有连接。

WSAENOTSOCK

此描述符不是套接字描述符。

参见:bind(), socket(), getsockname()。

6.2.6 getsockname()

语法:int WSAAPI

getsockname (

IN SOCKET s,

OUT struct sockaddr FAR* name,

IN OUT int FAR* namelen

);

此函数用来获取套接字的本地名。它检索指定套接字描述符的当前名字,并放入name,它用于参数s指定的一个已绑扎并且/或者已连接的套接字,返回与该套接字相连的本地地址。当调用connect()函数之前没有先调用bind()函数时,该调用特别有用;它提供了唯一一种用来确定系统设置的本地连接的方法。

参数

描述

s

一个已绑扎(bind())套接字的描述符。

name

接收套接字的地址(名字)的缓冲区指针。

namelen

指向name 缓冲区大小的指针,返回时,它含有返回名字的实际字节数。

返回值:如果没有错误发生,getsockname()返回0。否则返回值SOCKET_ERROR,错误码可通过调用WSAGetLastError()函数得到。

错误码:

WSANOTINITIALISED

未初始化Windows Sockets DLL,在使用此函数之前必须有一次成功的WSAStartup()函数调用。

WSAENETDOWN

Windows Sockets 实现检测到网络系统已经失败。

WSAEFAULT

参数name或namelen不是用户地址空间的合法部分,参数namelen不够大。

WSAEINPROGRESS

一个阻塞的Windows Sockets 操作正在进行。

WSAENOTSOCK

此描述符不是套接字描述符。

WSAEINVAL

套接字没有使用bind()绑扎到一个地址,或套接字在bind()调用时地址指定为ADDR_ANY,并且连接仍没有建立。

注释:流套接字只有在成功调用了bind(),connect()或accept()之后才真正与一名字联系。如果该套接字没有与一地址连接,调用返回其地址族,其它字段置为零。例如,一个网际地址域中的未连接套接字将会导致name所指的sockaddr_in结构中的sin_family字段被置为AF_INET,其它字段全置为零。如果套接字被绑扎为INADDR_ANY,这指示任何主机IP地址都可用于套接字,则getsockname()不一定返回主机IP地址的信息,除非该套接字已经用connect()或accept()建立了连接。Windows Sockets应用程序一定不要假定IP地址可从INADDR_ANY改变,这是因为对于一多宿主机来说,用于套接字的IP 地址是不可知的,除

非该套接字是已连接的。如果此套接字使用的是无连接协议,除非I/O正在该套接字上发生,否则得不到地址。

参见:bind(), socket(), getpeername()。

6.2.7 getsockopt()

语法:int WSAAPI

getsockopt (

IN SOCKET s,

IN int level,

IN int optname,

OUT char FAR* optval,

IN OUT int FAR* optlen

);

此函数用来获取套接字选项。它检索与任何类型、任何状态的套接字相连的套接字选项的当前值,并把结果存入optval。选项可能在多个协议层存在,但它们总是表现在最高的“socket”层。选项影响套接字操作,例如一个操作是否阻塞、包的路由选择、带外数据传输等。

参数

描述

s

套接字描述符。

level

设置选项的层,只支持SOL_SOCKET 和IPPROTO_TCP。

optname

指定要检索的套接字选项的名字。

optval

指向查询选项返回值的缓冲区。

optlen

指向optval缓冲区大小的指针。

返回值:如果没有错误发生,getsockname()返回0。否则返回值SOCKET_ERROR,错误码可通过调用WSAGetLastError()函数得到。

错误码:

WSANOTINITIALISED

未初始化Windows Sockets DLL,在使用此函数之前必须有一次成功的WSAStartup()函数调用。

WSAENETDOWN

Windows Sockets 实现检测到网络系统已经失败。

WSAEFAULT

参数optval或optlen不是用户地址空间的合法部分,或参数optlen不够大。

WSAEINPROGRESS

一个阻塞的Windows Sockets 操作正在进行。

WSAEINVAL

level未知或非法。

WSAENOTPROTOOPT

未知或不支持的选项。特别地,SOCK_STREAM类型的套接字不支持SO_BROADCAST,而SOCK_DGRAM类型的套接字不支持SO_ACCEPTCONN, SO_DONTLINGER, SO_KEEPALIVE, SO_LINGER和SO_OOBINLINE。

WSAENOTSOCK

此描述符不是套接字描述符。

注释:与选择的选项相关联的返回值放在缓冲区optval中,由optlen指向的整数指针开始应含有该缓冲区的大小,返回时,它被赋予返回值的长度大小。对于SO_LINGER,这将是结构linger的大小;对于其他选项,它将是一整形值的长度。如果选项从未由setsockopt()设置,则getsockopt()返回该选项的默认值。

getsockopt()支持下表所列选项,TYPE 标志optval指向的数据类型。TCP_NODELAY 选项使用IPPROTO_TCP层,其它选项使用SOL_SOCKET层。

C语言socket()函数

C语言socket()函数:建立一个socket通信 相关函数:accept, bind, connect, listen 头文件:#include #include 定义函数:int socket(int domain, int type, int protocol); 函数说明:socket()用来建立一个新的socket, 也就是向系统注册, 通知系统建立一通信端口. 参数domain 指定使用何种的地址类型, 完整的定义在/usr/include/bits/socket.h 内, 底下是常见的协议: PF_UNIX/PF_LOCAL/AF_UNIX/AF_LOCAL UNIX 进程通信协议 PF_INET?AF_INET Ipv4 网络协议 PF_INET6/AF_INET6 Ipv6 网络协议 PF_IPX/AF_IPX IPX-Novell 协议 PF_NETLINK/AF_NETLINK 核心用户接口装置 PF_X25/AF_X25 ITU-T X. 25/ISO-8208 协议 PF_AX25/AF_AX25 业余无线AX. 25 协议 PF_ATMPVC/AF_ATMPVC 存取原始ATM PVCs PF_APPLETALK/AF_APPLETALK appletalk (DDP)协议 PF_PACKET/AF_PACKET 初级封包接口

参数type 有下列几种数值: 1、SOCK_STREAM 提供双向连续且可信赖的数据流, 即TCP. 支持OOB 机制, 在所有数据传送前必须使用connect()来建立连线状态. 2、SOCK_DGRAM 使用不连续不可信赖的数据包连接 3、SOCK_SEQPACKET 提供连续可信赖的数据包连接 4、SOCK_RAW 提供原始网络协议存取 5、SOCK_RDM 提供可信赖的数据包连接 6、SOCK_PACKET 提供和网络驱动程序直接通信. protocol 用来指定socket 所使用的传输协议编号, 通常此参考不用管它, 设为0 即可. 返回值:成功则返回socket 处理代码, 失败返回-1. 错误代码: 1、EPROTONOSUPPORT 参数domain 指定的类型不支持参数type 或protocol 指定的协议 2、ENFILE 核心内存不足, 无法建立新的socket 结构 3、EMFILE 进程文件表溢出, 无法再建立新的socket 4、EACCESS 权限不足, 无法建立type 或protocol 指定的协议 5、ENOBUFS/ENOMEM 内存不足 6、EINVAL 参数domain/type/protocol 不合法 范例:参考connect().

什么是Socket

什么是Socket Socket接口是TCP/IP网络的API,Socket接口定义了许多函数或例程,程序员可以用它们来开发TCP/IP网络上的应用程序。要学Internet上的TCP/IP网络编程,必须理解Socket 接口。 Socket接口设计者最先是将接口放在Unix操作系统里面的。如果了解Unix系统的输入和输出的话,就很容易了解Socket了。网络的 Socket数据传输是一种特殊的I/O,Socket也是一种文件描述符。Socket也具有一个类似于打开文件的函数调用Socket(),该函数返回一个整型的Socket描述符,随后的连接建立、数据传输等操作都是通过该Socket实现的。常用的Socket类型有两种:流式Socket (SOCK_STREAM)和数据报式Socket(SOCK_DGRAM)。流式是一种面向连接的Socket,针对于面向连接的TCP服务应用;数据报式Socket是一种无连接的Socket,对应于无连接的UDP服务应用。 Socket建立 为了建立Socket,程序可以调用Socket函数,该函数返回一个类似于文件描述符的句柄。socket函数原型为: int socket(int domain, int type, int protocol); domain指明所使用的协议族,通常为PF_INET,表示互联网协议族(TCP/IP协议族);type参数指定socket的类型: SOCK_STREAM 或SOCK_DGRAM,Socket接口还定义了原始Socket (SOCK_RAW),允许程序使用低层协议;protocol通常赋值"0"。 Socket()调用返回一个整型socket描述符,你可以在后面的调用使用它。 Socket描述符是一个指向内部数据结构的指针,它指向描述符表入口。调用Socket函数时,socket执行体将建立一个Socket,实际上"建立一个Socket"意味着为一个Socket数据结构分配存储空间。Socket执行体为你管理描述符表。 两个网络程序之间的一个网络连接包括五种信息:通信协议、本地协议地址、本地主机端口、远端主机地址和远端协议端口。Socket数据结构中包含这五种信息。 Socket配置 通过socket调用返回一个socket描述符后,在使用socket进行网络传输以前,必须配置该socket。面向连接的socket客户端通过调用Connect函数在socket数据结构中保存本地和远端信息。无连接socket的客户端和服务端以及面向连接socket的服务端通过调用 bind函数来配置本地信息。 Bind函数将socket与本机上的一个端口相关联,随后你就可以在该端口监听服务请求。Bind 函数原型为: int bind(int sockfd,struct sockaddr *my_addr, int addrlen); Sockfd是调用socket函数返回的socket描述符,my_addr是一个指向包含有本机IP地址及端口号等信息的sockaddr类型的指针;addrlen常被设置为sizeof(struct sockaddr)。 struct sockaddr结构类型是用来保存socket信息的: struct sockaddr { unsigned short sa_family; /* 地址族, AF_xxx */ char sa_data[14]; /* 14 字节的协议地址 */ }; sa_family一般为AF_INET,代表Internet(TCP/IP)地址族;sa_data则包含该socket 的IP地址和端口号。 另外还有一种结构类型: struct sockaddr_in {

PHPsocket函数讲解

PHPsocket函数讲解 PHPsocket函数讲解 代码如下: extension=php_sockets.dll 如果你无法去掉注释,那么请使用下面的代码来加载扩展库: 代码如下: if(!extension_loaded('sockets')){ if(strtoupper(substr(PHP_OS,3))=="WIN"){ dl('php_sockets.dll'); }else{ dl('sockets.so'); } } 如果你不知道你的socket是否打开,那么你可以使用phpinfo()函数来确定socket是否打开。你通过查看phpinfo信息了解 socket是否打开。 phpsocket相关函数如下: 代码如下: socket_accept()接受一个Socket连接 socket_bind()把socket绑定在一个IP地址和端口上 socket_clear_error()清除socket的错误或者最后的错误代码socket_close()关闭一个socket资源

socket_connect()开始一个socket连接 socket_create_listen()在指定端口打开一个socket监听 socket_create_pair()产生一对没有区别的socket到一个数组里 socket_create()产生一个socket,相当于产生一个socket的数据结构 socket_get_option()获取socket选项 socket_getpeername()获取远程类似主机的'ip地址 socket_getsockname()获取本地socket的ip地址 socket_iovec_add()添加一个新的向量到一个分散/聚合的数组 socket_iovec_alloc()这个函数创建一个能够发送接收读写的iovec数据结构 socket_iovec_()删除一个已经分配的iovec socket_iovec_fetch()返回指定的iovec资源的数据 socket_iovec_free()释放一个iovec资源 socket_iovec_set()设置iovec的数据新值 socket_last_error()获取当前socket的最后错误代码 socket_listen()监听由指定socket的所有连接 socket_read()读取指定长度的数据 socket_readv()读取从分散/聚合数组过来的数据 socket_recv()从socket里结束数据到缓存 socket_recvfrom()接受数据从指定的socket,如果没有指定则默认当前socket socket_recvmsg()从iovec里接受消息

socket原理详解

socket原理详解 1、什么是socket 我们知道进程通信的方法有管道、命名管道、信号、消息队列、共享内存、信号量,这些方法都要求通信的两个进程位于同一个主机。但是如果通信双方不在同一个主机又该如何进行通信呢?在计算机网络中我们就学过了tcp/ip协议族,其实使用tcp/ip协议族就能达到我们想要的效果,如下图(图片来源于《tcp/ip协议详解卷一》第一章1.3) 、 图一各协议所处层次 当然,这样做固然是可以的,但是,当我们使用不同的协议进行通信时就得使用不同的接口,还得处理不同协议的各种细节,这就增加了开发的难度,软件也不易于扩展。于是UNIX BSD就发明了socket这种东西,socket屏蔽了各个协议的通信细节,使得程序员无需关注协议本身,直接使用socket提供的接口来进行互联的不同主机间的进程的通信。这就好比操作系统给我们提供了使用底层硬件功能的系统调用,通过系统调用我们可以方便的使用磁盘(文件操作),使用内存,而无需自己去进行磁盘读写,内存管理。socket其实也是一样的东西,就是提供了tcp/ip

协议的抽象,对外提供了一套接口,同过这个接口就可以统一、方便的使用tcp/ip协议的功能了。百说不如一图,看下面这个图就能明白了。 图二 socket所处层次 那么,在BSD UNIX又是如何实现这层抽象的呢?我们知道unix中万物皆文件,没错,bsd在实现上把socket设计成一种文件,然后通过虚拟文件系统的操作接口就可以访问socket,而访问socket时会调用相应的驱动程序,从而也就是使用底层协议进行通信。(vsf也就是unix提供给我们的面向对象编程,如果底层设备是磁盘,就对磁盘读写,如果底层设备是socket就使用底层协议在网中进行通信,而对外的接口都是一致的)。下面再看一下socket的结构是怎样的(图片来源于《tcp/ip协议详解卷二》章节一,1.8描述符),注意:这里的socket是一个实例化之后的socket,也就是说是一个具体的通信过程中的socket,不是指抽象的socket结构,下文还会进行解释。

socket函数解读

socket函数说明 1、accept(接受socket连线) 相关函数 socket,bind,listen,connect 定义函数 int accept(int s,struct sockaddr * addr,int * addrlen); 函数说明 accept()用来接受参数s的socket连线。参数s的socket必需先经bind()、listen()函数处理过,当有连线进来时accept()会返回一个新的socket处理代码,往后的数据传送与读取就是经由新的socket处理,而原来参数s的socket能继续使用accept()来接受新的连线要求。连线成功时,参数addr所指的结构会被系统填入远程主机的地址数据,参数addrlen为scokaddr的结构长度。关于结构sockaddr的定义请参考bind()。 返回值成功则返回新的socket处理代码,失败返回-1,错误原因存于errno中。 错误代码 EBADF 参数s 非合法socket处理代码。 EFAULT 参数addr指针指向无法存取的内存空间。 ENOTSOCK 参数s为一文件描述词,非socket。 EOPNOTSUPP 指定的socket并非SOCK_STREAM。 EPERM 防火墙拒绝此连线。 ENOBUFS 系统的缓冲内存不足。 ENOMEM 核心内存不足。 范例参考listen()。 2、bind(对socket定位) 相关函数 socket,accept,connect,listen 定义函数 int bind(int sockfd,struct sockaddr * my_addr,int addrlen); 函数说明 bind()用来设置给参数sockfd的socket一个名称。此名称由参数my_addr指向一sockaddr结构,对于不同的socket domain定义了一个通用的数据结构 struct sockaddr { unsigned short int sa_family; char sa_data[14]; }; sa_family 为调用socket()时的domain参数,即AF_xxxx值。 sa_data 最多使用14个字符长度。 此sockaddr结构会因使用不同的socket domain而有不同结构定义,例如使用AF_INET domain,其socketaddr 结构定义便为 struct socketaddr_in { unsigned short int sin_family; uint16_t sin_port; struct in_addr sin_addr; unsigned char sin_zero[8]; }; struct in_addr { uint32_t s_addr;

SOCKET函数详解(My整理)

Socket 函数说明 1.1 库函数综述 1.1.1 套接字函数 表 1.1 Windows Sockets 1.1 版本Berkeley Sockets函数 函数名说明 accept()确认外来连接,并将它与一个立即建立的数据套接字联系起来。原始套 接字返回到监听状态 bind() 给未命名套接字赋一个本地名 closesocket()从进程对象参考表中删去一个套接字,只有当SO_LINGER设置时才阻塞connect()在指定套接字上初始化连接 getpeername() 获取与指定套接字连接的对等方的名字 getsockname() 获取指定套接字的当前名字 getsockopt() 获取与指定套接字相关的选项 htonl() 将一个32位数从主机字节顺序转换为网络字节顺序 htons() 将一个16 位数从主机字节顺序转换为网络字节顺序 inet_addr() 将一个用网际标准点分表示法表示的字符串地址转换成网际地址值 inet_ntoa() 将一个网际地址值转换成一个用点分十进制表示法表示的字符串地址ioctlsocket() 为套接字提供控制 listen() 在指定套接字上监听外来连接 ntohl() 将一个32位数从网络字节顺序转换为主机字节顺序 ntohs() 将一个16 位数从网络字节顺序转换为主机字节顺序 recv()从一个连接的套接字上接收数据 recvfrom()从一个连接或未连接的套接字上接收数据 select()执行多路同步I/O send()给一个连接套接字发送数据 sendto()给一个连接或未连接套接字发送数据 setsockopt() 设置与指定套接字相关的选项 shutdown() 关闭全双工连接的一部分 socket() 建立一个通讯用的末端点,返回一个套接字 注:标红函数作用在阻塞套接字上可以阻塞。 这些函数根据功能的不同可以分为如下几类: (1) 套接字函数。此类函数包括socket(),bind(),getpeername(),getsockname()和closesocket(),它们主要完成创建,关闭套接字功能,以及对套接字命名与名字获取。 (2) 网络连接函数。此类函数包括listen() ,accept(),connect()和shutdown(),它们完成网络连接(如虚电路)的建立与关闭。此类函数中有部分可阻塞。 (3) 数据传输函数。此类函数包括send(),recv() ,sendto()和recvfrom() ,它们完成网络数据的发送与接收,全部是可以阻塞的函数。 (4) 字节定序函数。此类函数包括htonl(),htons(),ntohl()和ntohs(),它们完成主机/网络之间数据字节顺序的转换。 (5) 地址转换函数。此类函数包括inet_addr(),inet_ntoa(),它们完成网络字符串地址和Internet 地址之间的转换。 (6) 套接字控制函数。此类函数包括getsockopt(),setsockopt(),ioctlsocket()和select(),它们设置/获取套接字的选项,控制/检测套接字的工作状态。其中select()函数在必要时可能阻塞。 只使用了上述函数Berkeley Sockets 源程序基本上可以不加修改地移植到Windows Sockets 环境中来。但是,移植过来的程序有一个最大的问题是“阻塞”。在Berkeley Sockets 中,套接字默认的工作模式是操作处于阻塞方式,一个阻塞操作可能阻塞整个Windows 环境。在非抢先Windows环境,强烈推荐程序员使用非阻塞(异步)操作,也就是说,推荐使用Windows Sockets 提供的异步选择函数代替可能阻塞的select()函数,并且用网络事件消息来驱动可能阻塞的网络连接函数(accept()和connect())和数据传输函数,这样设计的程序能更好地工作。 1.1.2 数据库函数 Windows Sockets定义了如表1.2 所示的“数据库”函数:

linux socket编程基础(必读)

socket编程 Linux下Socket编程基础(实例) 1、引言 Linux的兴起可以说是Internet创造的一个奇迹。Linux作为一个完全开放其原代码的免费的自由软件,兼容了各种UNIX标准(如POSIX、UNIX System V和BSD UNIX等)的多用户、多任务的具有复杂内核的操作系统。在中国,随着Internet的普及,一批主要以高等院校的学生和ISP的技术人员组成的Linux爱好者队伍已经蓬勃成长起来。越来越多的编程爱好者也逐渐酷爱上这个优秀的自由软件。本文介绍了Linux下Socket的基本概念和函数调用。 2、什么是Socket Socket(套接字)是通过标准的UNIX文件描述符和其它程序通讯的一个方法。每一个套接字都用一个半相关描述:{协议,本地地址、本地端口}来表示;一个完整的套接字则用一个相关描述:{协议,本地地址、本地端口、远程地址、远程端口},每一个套接字都有一个本地的由操作系统分配的唯一的套接字号。 3、Socket的三种类型 (1)流式Socket(SOCK_STREAM) 流式套接字提供可靠的、面向连接的通信流;它使用TCP协议,从而保证了数据传输的正确性和顺序的。 (2)数据报Socket(SOCK_DGRAM)

数据报套接字定义了一种无连接的服务,数据通过相互独立的报文进行传输,是无序的,并且不保证可靠、无差错。它使用数据报协议UDP (3)原始Socket 原始套接字允许对底层协议如IP或ICMP直接访问,它功能强大但使用较为不便,主要用于一些协议的开发。 4、利用套接字发送数据 1、对于流式套接字用系统调用send()来发送数据。 2、对于数据报套接字,则需要自己先加一个信息头,然后调用sendto()函数把数据发送出去。 5、Linux中Socket的数据结构 (1)struct sockaddr{//用于存储套接字地址 unsigned short sa_family;//地址类型 char sa_data[14];//14字节的协议地址 }; (2)struct sockaddr_in{//in代表internet short int sin_family;//internet协议族 unsigned short int sin_port;//端口号,必须是网络字节顺序 struct in_addr sin_addr;//internet地址,必须是网络字节顺序 unsigned char sin_zero;//添0(和struct sockaddr一样大小 };

c语言的SOCKET(非常好的参考)

介绍 Socket 编程让你沮丧吗?从man pages中很难得到有用的信息吗?你想跟上时代去编Internet相关的程序,但是为你在调用connect() 前的bind() 的结构而不知所措?等等… 好在我已经将这些事完成了,我将和所有人共享我的知识了。如果你了解 C 语言并想穿过网络编程的沼泽,那么你来对地方了。-------------------------------------------------------------------------------- 读者对象 这个文档是一个指南,而不是参考书。如果你刚开始socket 编程并想找一本入门书,那么你是我的读者。但这不是一本完全的socket 编程书。 -------------------------------------------------------------------------------- 平台和编译器 这篇文档中的大多数代码都在Linux 平台PC 上用GNU 的gcc 成功编译过。而且它们在HPUX平台上用gcc 也成功编译过。但是注意,并不是每个代码片段都独立测试过。 --------------------------------------------------------------------------------

目录: 1) 什么是套接字? 2) Internet 套接字的两种类型 3) 网络理论 4) 结构体 5) 本机转换 6) IP 地址和如何处理它们 7) socket()函数 8) bind()函数 9) connect()函数 10) listen()函数 11) accept()函数 12) send()和recv()函数 13) sendto()和recvfrom()函数 14) close()和shutdown()函数 15) getpeername()函数 16) gethostname()函数 17) 域名服务(DNS) 18) 客户-服务器背景知识 19) 简单的服务器 20) 简单的客户端 21) 数据报套接字Socket

Socket send函数和recv函数详解

int send( SOCKET s, const char FAR *buf, int len, int flags ); 不论是客户还是服务器应用程序都用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信号,进程对该信号的默认处理是进程终止。 通过测试发现,异步socket的send函数在网络刚刚断开时还能发送返回相应的字节数,同时使用select检测也是可写的,但是过几秒钟之后,再send就会出错了,返回-1。select 也不能检测出可写了。 recv函数 int recv( SOCKET s, char FAR *buf, int len, int flags );

windows—socket函数整理

Select模型 Select模型是Windows sockets中最常见的IO模型。它利用select函数实现IO 管理。通过对select函数的调用,应用程序可以判断套接字是否存在数据、能否向该套接字写入数据。 如:在调用recv函数之前,先调用select函数,如果系统没有可读数据那么select函数就会阻塞在这里。当系统存在可读或可写数据时,select函数返回,就可以调用recv函数接收数据了。可以看出使用select模型,需要两次调用函数。第一次调用select函数第二次socket API。使用该模式的好处是:可以等待多个套接字。 select函数中需要三个fd_set结构: 一:准备接收数据的套接字集合,即可读性集合。 二:准备发送数据的套接字集合,即可写性集合。 在select函数返回时,会在fd_set结构中,填入相应的套接字。 readfds数组将包括满足以下条件的套接字: 1:有数据可读。此时在此套接字上调用recv,立即收到对方的数据。 2:连接已经关闭、重设或终止。 3:正在请求建立连接的套接字。此时调用accept函数会成功。 writefds数组包含满足下列条件的套接字: 1:有数据可以发出。此时在此套接字上调用send,可以向对方发送数据。 2:调用connect函数,并连接成功的套接字。 exceptfds数组将包括满足下列条件的套接字: 1:调用connection函数,但连接失败的套接字。 2:有带外(out of band)数据可读。 select函数的使用: 在调用select函数对套接字进行监视之前,必须将要监视的套接字分配给上述三个数组中的一个。然后调用select函数,再次判断需要监视的套接字是否还在原来的集合中。就可以知道该集合是否正在发生IO操作。 例如:应用程序想要判断某个套接字是否存在可读的数据,需要进行如下步骤:1:将该套接字加入到readfds集合。 2:以readfds作为第二个参数调用select函数。 3:当select函数返回时,应用程序判断该套接字是否仍然存在于readfds集合。 4:如果该套接字存在与readfds集合,则表明该套接字可读。此时就可以调用recv 函数接收数据。否则,该套接字不可读。

套接字socket函数详解

一、创建套接字---socket() SOCKET sclient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 原型: socket( _In_int af,//通信发生的区域 _In_int type,//socket类型 _In_int protocol//该套接字使用的特定协议 ); 二、绑定本地址和端口----bind() 原型: bind(//没错返回0,否则返回SOCKET_ERROR _In_SOCKET s,//套接字描述符 _In_reads_bytes_(namelen) const struct sockaddr FAR * name,//name是赋给套接字的本地地址名字,长度可变,结构随通信域不同而不同 _In_int namelen//表明name的长度 ); 三、建立套接字连接-----connect()与accept() 原型: int PASCAL FAR connect ( _In_ SOCKET s,//本地套接字描述符 _In_reads_bytes_(namelen) const struct sockaddr FAR *name,//name 指出说明对方套接字地址结构的指针 _In_ int namelen//表明name的长度 ); 原型: accept(//返回一个SOCKET类型的值,表示接收到的套接字的描述符,否则返回INVALID_SOCKET _In_SOCKET s, _Out_writes_bytes_opt_(*addrlen) struct sockaddr FAR * addr,//客户的地址_Inout_opt_int FAR * addrlen//客户方套接字地址的长度(字节数) ); 四、监听连接---listen() listen()必须在accept()之前调用 原型: listen( _In_SOCKET s,//标识一个本地已经建立的尚未连接的套接字号 _In_int backlog//标识请求队列的最大长度,用于限制排队请求的个数,最大为5.没有错误此函数返回0,否则返回SOCKET_ERROR ); 五、数据传输与接收----send()与recv()

一个简单的SOCKET程序的数据包结构和封解包函数

一个简单的SOCKET程序的数据包结构和封解包函 数 练习写套接字通信程序时候写的一段代码,本来想写个聊天室但写来写去 进度卡在界面上接节下来都是通信部分的代码因为只是试验用所以都是用C写 的,等界面部分完工后会用类来封装一下因为本人E文很烂所以变量和函数的 命名是具有中国特色的,求理解.不过我注释的很详细了谨以此文纪念我那坑 爹的编程自学生涯......................#include “stdio.h”#include//////////////////////////////数据包接构////////////////////////////////////////数据包类型CTOS 为客户端使用的数据包, STOC 为服务端使用的数据包#define CTOS 1#define STOC 2//数据包存储管道每个包最大为2000 字节,其中数据载荷为最大1800 字节,其余留着扩展数据 包头struct SJGD {BYTE sjgd[2000]; //数据缓冲区DWORD sjcd; //数据长度};//数据包头大小为8 字节struct MSG_TOU { DWORD lxid; //数据包类型DWORD sxid; //数据包顺序标号DWORD sjbcd; //数据包长度};//服务端-》客户端包struct MSG_STOC { DWORD cmd; //命令标识DWORD sjbcd; //整个MSG_STOC 数据包缓冲区的长度BYTE shuju[1000]; //附加数据缓冲区};//客户 端-》服务器包struct MSG_CTOS { DWORDcmd; //命令标识DWORD sjbcd; //整个MSG_CTOS 数据包缓冲区的长度BYTE shuju[1800]; //附加数据缓冲区};//共 用体union MSG_DATA { struct MSG_STOC msg_stoc; struct MSG_CTOS msg_ctos; };//完整数据包struct SJB {struct MSG_TOU tou; //数据包头unionMSG_DATA data; //数据缓冲区}; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////封包函数第一个参数为数据包类型,第二个为命令标 识,这是数据包的重点远控命令会转换成数字在这里传输//第三个为数据包顺序

实验06 Socket编程基础练习

实验六Socket编程基础练习 1.实验目的 1)掌握Socket地址及其操作 2)掌握Socket基本函数,如socket、bing、listen、accept、send、recv 等的应用 2. 实验前的准备 3)阅读教材关于TCP/IP体系结构及数据包格式的相关内容 4)阅读教材关于Socket的相关内容 5)阅读WinSock编程指南 6)阅读本实验所附内容 7)熟悉VC++、C#或Java开发语言 3.实验内容 利用Java或C++语言,分别基于TCP和UDP编写一个简单的 Client/Server网络应用程序。要求实现客户向服务器传输任意一个字符串,服务器将收到的字符串变换成大写后传回客户。 4.实验方式 每位同学上机编程实验,实验指导教师现场指导。Socket编程基础知识可参考附录中的内容。 5.实验报告 在实验报告中要说明Socket编程的客户端和服务器端主要步骤、利用开发语言语言用到的主要类及其主要作用、实验过程和实验结果。

预备知识 1.进程到进程的通信 通信数据传输到计算机后,计算机必须区分各个进程的通信数据并提交给网络通信进程进行相应的处理,使用了ip地址加端口来区分具体的进程数据(ip:port)。 2. 套接字的类型 为了满足不同的通信程序对通信质量和性能的要求,一般的网络系统提供了三种不同类型的套接口,以供用户在设计网络应用程序时根据不同的要求来选择,三种类型套接口: ?流式套接口(SOCK_STREAM) ?数据报套接口(SOCK_DGRAM) ?原始套接口(SOCK_RAW) 3.地址结构 三种地址结构: sockaddr_in : INET 协议族地址结构 in_addr : IPv4地址结构 sockaddr : 通用地址结构 3.1 INET 协议族地址结构 struct sockaddr _ in { short sin_family ; // 地址族 u_short sin_prot ; // 端口号 struct in_addr sin_addr ; // IP地址 char sin_zero [ 8 ] ; } ; ?sin_family :地址族,一般填为AF_INET ?另一组和AF_XXX 类似的PF_XXX 常量,与AF_INET 相对应有 PF_INET 。

C语言编程-socket基础

C语言编程---socket基础 2008-07-16 10:22文章来源:https://www.doczj.com/doc/2014253570.html,/sdghgk 先说套接字,网络编程必不可少的东西.先看下面吧,这可是经典哦! 最初socket是为支持TCP/IP协议而开发的,现在它已被认为是开发非RPC Windows网络应用程序的最好途径。 socket作为BDS UNIX的进程通信机制,是进行程序间通讯(IPC)的 BSD 方法,这意味着 socket 用来让一个进程和其他的进程互通信息。 所谓socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄。应用程序通常通过"套接字"向网络发出请求或者应答网络请求。 开发原理: 服务器,使用ServerSocket监听指定的端口,端口可以随意指定(由于1024以下的端口通常属于保留端口,在一些操作系统中不可以随意使用,所以建议使用大于1024的端口),等待客户连接请求,客户连接后,会话产生;在完成会话后,关闭连接。 客户端,使用Socket对网络上某一个服务器的某一个端口发出连接请求,一旦连接成功,打开会话;会话完成后,关闭Socket。客户端不需要指定打开的端口,通常临时的、动态的分配一个1024以上的端口。 -- win API socket 本文所谈到的Socket函数如果没有特别说明,都是指的Windows Socket API。 一、WSAStartup函数 int WSAStartup( WORD wVersionRequested, LPWSADATA lpWSAData ); 使用Socket的程序在使用Socket之前必须调用WSAStartup函数。该函数的第一个参数指明程序请求使用的Socket版本,其中高位字节指明副版本、低位字节指明主版本;操作系统利用第二个参数返回请求的Socket 的版本信息。当一个应用程序调用WSAStartup函数时,操作系统根据请求的Socket版本来搜索相应的Socket 库,然后绑定找到的Socket库到该应用程序中。以后应用程序就可以调用所请求的Socket库中的其它Socket 函数了。该函数执行成功后返回0。 例:假如一个程序要使用2.1版本的Socket,那么程序代码如下 wVersionRequested = MAKEWORD( 2, 1 ); err = WSAStartup( wVersionRequested, &wsaData ); 二、WSACleanup函数 int WSACleanup (void); 应用程序在完成对请求的Socket库的使用后,要调用WSACleanup函数来解除与Socket库的绑定并且释放Socket库所占用的系统资源。 三、socket函数 SOCKET socket( int af, int type, int protocol ); 应用程序调用socket函数来创建一个能够进行网络通信的套接字。第一个参数指定应用程序使用的通信协议的协议族,对于TCP/IP协议族,该参数置PF_INET;第二个参数指定要创建的套接字类型,流套接字类型为SOCK_STREAM、数据报套接字类型为SOCK_DGRAM;第三个参数指定应用程序所使用的通信协议。该函数如果调用成功就返回新创建的套接字的描述符,如果失败就返回INVALID_SOCKET。套接字描述符是一个整数类型的值。每个进程的进程空间里都有一个套接字描述符表,该表中存放着套接字描述符和套接字数据结构的对应关系。该表中有一个字段存放新创建的套接字的描述符,另一个字段存放套接字数据结构的地址,因此根据

Socket编程(最新,带例程)c语言

最新版Socket编程,后面带有程序实例,并通过调试,可以直接编译运行;希望对大家有帮助。 网络的Socket数据传输是一种特殊的I/O,Socket也是一种文件描述符。Socket也具有一个类似于打开文件的函数调用Socket(),该函数返回一个整型的Socket描述符,随后的连接建立、数据传输等操作都是通过该Socket实现的。 什么是Socket Socket接口是TCP/IP网络的API,Socket接口定义了许多函数或例程,程序员可以用它们来开发TCP/IP网络上的应用程序。要学Internet上的TCP/IP网络编程,必须理解Socket接口。 Socket接口设计者最先是将接口放在Unix操作系统里面的。如果了解Unix系统的输入和输出的话,就很容易了解Socket了。网络的 Socket数据传输是一种特殊的I/O,Socket也是一种文件描述符。Socket也具有一个类似于打开文件的函数调用Socket(),该函数返回一个整型的Socket描述符,随后的连接建立、数据传输等操作都是通过该Socket实现的。常用的Socket类型有两种:流式Socket (SOCK_STREAM)和数据报式Socket(SOCK_DGRAM)。流式是一种面向连接的Socket,针对于面向连接的TCP服务应用;数据报式Socket是一种无连接的Socket,对应于无连接的UDP服务应用。 Socket建立 为了建立Socket,程序可以调用Socket函数,该函数返回一个类似于文件描述符的句柄。socket函数原型为: int socket(int domain, int type, int protocol); domain指明所使用的协议族,通常为PF_INET,表示互联网协议族(TCP/IP协议族);type参数指定socket的类型: SOCK_STREAM 或SOCK_DGRAM,Socket 接口还定义了原始Socket(SOCK_RAW),允许程序使用低层协议;protocol通常赋值 "0"。 Socket()调用返回一个整型socket描述符,你可以在后面的调用使用它。 Socket描述符是一个指向内部数据结构的指针,它指向描述符表入口。调用Socket函数时,socket执行体将建立一个Socket,实际上 "建立一个Socket"意味着为一个Socket数据结构分配存储空间。Socket执行体为你管理描述符表。两个网络程序之间的一个网络连接包括五种信息:通信协议、本地协议地址、本地主机端口、远端主机地址和远端协议端口。Socket数据结构中包含这五种信息。 Socket配置 通过socket调用返回一个socket描述符后,在使用socket进行网络传输以前,必须配置该socket。面向连接的socket客户端通过调用Connect函数在socket数据结构中保存本地和远端信息。无连接socket的客户端和服务端以及面向连接socket的服务端通过调用bind函数来配置本地信息。

C++socket编程详解

第1章Visual C++网络编程概述 Visual C++(后面简写为VC)网络编程是指用户使用MFC类库(微软基础类库)在VC编译器中编写程序,以实现网络应用。用户通过VC编程实现的网络软件可以在网络中不同的计算机之间互传文件、图像等信息。本章将向用户介绍基于Windows操作系统的网络编程基础知识,其开发环境是VC。在VC 编译器中,使用Windows Socket进行网络程序开发是网络编程中非常重要的一部分。 1.1 网络基础知识 如果用户要进行VC网络编程,则必须首先了解计算机网络通信的基本框架和工作原理。在两台或多台计算机之间进行网络通信时,其通信的双方还必须遵循相同的通信原则和数据格式。本节将向用户介绍OSI七层网络模型、TCP/IP协议以及C/S编程模型。 1.1.1 OSI七层网络模型 OSI网络模型是一个开放式系统互联的参考模型。通过这个参考模型,用户可以非常直观地了解网络通信的基本过程和原理。OSI参考模型如图1.1所示。 图1.1 OSI七层网络模型 用户从OSI网络模型可以很直观地看到,网络数据从发送方到达接收方的过程中,数据的流向以及经过的通信层和相应的通信协议。事实上在网络通信的发送端,其通信数据每到一个通信层,都会被该层协议在数据中添加一个包头数据。而在接收方恰好相反,数据通过每一层时都会被该层协议剥去相应的

包头数据。用户也可以这样理解,即网络模型中的各层都是对等通信。在OSI 七层网络模型中,各个网络层都具有各自的功能,如表1.1所示。 表1.1 各网络层的功能 注意:在表 1.1中列出了OSI 七层网络模型中各层的基本功能概述。用户根据这些基本的功能概述会对该网络模型有一个比较全面的认识。 1.1.2 TCP/IP 协议 TCP/IP 协议实际上是一个协议簇,其包括了很多协议。例如,FTP (文本传输协议)、SMTP (邮 件传输协议)等应用层协议。TCP/IP 协议的网络模 型只有4层,包括数据链路层、网络层、数据传输层和应用层,如图1.2所示。 在TCP/IP 网络编程模型中,各层的功能如表1.2所示。 表1.2 TCP/IP 网络协议各层功能 在数据传输层中,包括了TCP 和UDP 协议。其中,TCP 协议是基于面向连接的可靠的通信协议。其具有重发机制,即当数据被破坏或者丢失时,发送方将重发该数据。而UDP 协议是基于用户数据报协议,属于不可靠连接通信的协议。例如,当用户使用UDP 协议发送一条消息时,并不知道该消息是否已经到达接收方,或者在传输过程中数据已经丢失。但是在即时通信中,UDP 协议在对一些对时间要求较高的网络数据传输方面有着重要的 作用。 1.1.3 C/S 编程模型 C/S 编程模型是基于可靠连接的通信模型。在通信的双方必须使用各自的IP 地址以及端口进行通信。否则,通信过程将无法实现。通常情况下,当用户使用C/S 模型进行通信时,其通信的任意一方称为客户端,则另一方称为服务器端。 图1.2 TCP/IP 网络协议模型

相关主题
文本预览
相关文档 最新文档