首页 > 编程知识 正文

socket常见问题,以下关于socket的描述错误的

时间:2023-05-06 06:28:48 阅读:186083 作者:70

1.socketsocketsocket(intaf,int type,int protocol );

af :始终为AF_INET

使用其他地址族id,如AF_ISO,而不是AF_INET。

返回:-1。

错误: 10047 (使用了与请求的协议不兼容的地址) )。

type,通常为SOCK_STREAM或SOCK_DGRAM

头文件中只定义了以下标准类型:

#define SOCK_STREAM 1

#define SOCK_DGRAM 2

#define SOCK_RAW 3

#define SOCK_RDM 4

#define SOCK_SEQPACKET 5

使用上面未定义的类型。

返回:-1。

错误: 10044 (此地址族不支持指定的插槽类型) )。

协议,通常为0

type=SOCK_STREAM,protocol=6

普通type=SOCK_STREAM,protocol=7

返回:-1

错误号: 10043 (请求的协议尚未配置在系统中或可能不存在) type=SOCK_DGRAM,protocol=17

普通type=SOCK_DGRAM,protocol=19

返回:-1

错误: 10043 (所请求的协议尚未配置在系统中或可能不存在)结论

套接字暂时仅支持AF_INET协议系列。 非标准套接字类型不支持。 如果协议编号参数为0,则使用与套接字类型相对应的协议编号。 否则,协议编号的参数必须与相应的套接字类型相同。 2.bindintbind(sockets,const struct sockaddr FAR* name,int namelen );

s

在套接字上不请求资源的套接字上操作。

返回:-1

错误号: 10038 (在套接字以外尝试了操作)

使用name,通常是AF_INET地址族,inaddr_any(0)地址

在local结构中,sin_family成员被指派给AF_OSI。

返回:-1

错误代码:在10047 (使用与请求的协议不兼容的地址) local结构中,sin_addr成员分配给主计算机的IP地址,在local结构中,sin_addr成员分配给非主计算机的IP地址和团队另一个同学的IP地址一样。

返回:-1

错误代码: 10049 (在该上下文中,请求的地址无效。 在local结构中,sin_port成员被指派为135。

返回:-1

错误代码: 10048 (通常每个套接字地址(协议/网络地址/端口)只能使用一次) namelen通常如sizeof(sockaddr_in )

namelen=10

返回:-1

错误代码: 10014 (尝试在某个调用中使用指针参数时检测到无效的指针地址(namelen=16 )

返回: 0

普通namelen=40

返回: 0

正常的结论

可以绑定本机所有的地址(或INADDR_ANY ),非本机所有的地址错误。 bind已在使用的端口值将会出错。 len参数必须大于或等于地址结构实际占用的长度。 思考

本机可以有多个IP,所以需要一种指示从哪个实体接收数据的方法。 当然,必须提供表达“从所有实体收到”的方法。 在头文件中INADDR_ANY被明确定义为0。 关于bind使用的端口。 意味着端口被绑定,上层还活着。 处于(未设置复用)等待时间状态的端口被占用,实际上绑定成功,但连接失败。 详见关于TIME-WAIT的备忘录,第六条。 3.listenintlisten(sockets,int backlog );

s

使用尚未半相关的套接字。 (bind失败时)

返回:-1

错误编号: 10022 (指定了无效的参数)

后台日志

我纯粹引用。 ((没有出处) ) ) ) ) ) )。

“在windows套接字实现中,服务器最多只能同时接收五个套接字。 如果使用参数0,系统会将参数更改为1,如果使用大于5的值,系统会自动将参数更改为5。 ”

设置参数值为0,表示一个客户端可以同时连接到服务器(在vista中可以连接两个,有时可以连接三个,-_0//) )

参数值为1,有1个客户机可同时与服务器连接设置参数值为10,有10个客户机可同时与服务器连接

结论

第一个参数的套接字必须是成功bind过后的。监听个数为0的话,会自动设置为1。最大监听个数在XP SP3下可以超过5。

问题

如何获得实际的backlog值? 
MSDN: There is no standard provision to obtain the actual backlog value.

如何结束套接字的监听状态? 
首先,close掉是可以的。如果不close呢?最初猜想backlog为0,-1等特殊值可以达到此效果,结果失败。求解。

4.accept

SOCKET accept( SOCKET s, struct sockaddr FAR* addr, int FAR* addrlen );


在没有listen的套接字上面。 
返回:-1 
错误号:10022(提供了一个无效的参数)

addr,输出参数,一般不填 
单机测试,填上本机的IP和某个端口号。 
结果:无法限制所接收的地址,执行完后addr中存放实际的地址。

addrlen 
同bind

结论

主套接字必须处于监听状态。在地址字段填上任何值不能限制接受的连接。len参数要求所携带的值大于等于16。(AF_INET地址结构的长度)5.recv

int recv( SOCKET s, char FAR* buf, int len, int flags ); 
对于服务器,一般是ns = accept(s , &addr , &len) ;

s,一般是用上面accept正常返回的值

在没有accept的从套接字上操作。(上面的ns) 
返回:-1 
错误号:10038(在一个非套接字上尝试了一个操作)

在主套接字上操作。(上面的s) 
返回:-1 
错误号:10057(由于套接字没有连接并且 
(当使用一个 sendto 调用发送数据报套接字时)没有提供地址, 
发送或接收数据的请求没有被接受。 )

buf,要求指向一个有效的缓冲区 
如果指向的无效的内存区域 
返回: -1 
错误号:10014(系统检测到在一个调用中尝试使用指针参数时的无效指针地址)

len,发送的字节数 
len过长可能造成缓冲区溢出。 
这个属于编程中的普遍考虑问题,不是socket函数特有。

flags,一般用0 
设置MSG_PEEK标志后,接收但不移除数据。 
(再次接收可得到相同的数据)

结论

对服务器来说,必须传递成功accept之后返回的套接字。缓冲区指针所指位置必须有效。缓冲区长度参数不可超过实际准备的缓冲区长度。MSG_PEEK标志在接收的时候将保留数据。6.send

int send( SOCKET s, const char FAR* buf, int len, int flags );

s,同recv

在没有accept的从套接字上操作。(上面的ns) 
返回:-1 
错误号:10038(在一个非套接字上尝试了一个操作)

在主套接字上操作。(上面的s) 
返回:-1 
错误号:10057(由于套接字没有连接并且 
(当使用一个 sendto 调用发送数据报套接字时)没有提供地址, 
发送或接收数据的请求没有被接受。 )

buf 
必须指向有效缓冲区,同recv

len 
必须和要发送的数据长度一致。

结论 
除flag可选项不同外,和recv一致。

7.closesocket

int closesocket( SOCKET s );

s

在申请套接字资源(调用socket)之前closesocket 
返回: -1 
错误号:10038(在一个非套接字上尝试了一个操作)

再已经closesocket的套接字上closesocket 
返回: -1 
错误号:10038(在一个非套接字上尝试了一个操作)

结论 
s必须是有效打开的套接字。 
不得重复关闭。

8.connect

int connect( SOCKET s, const struct sockaddr FAR* name, int namelen );

没有对端响应的情况 
在没有运行服务器的情况下,connect是否会一直阻塞? 
结果:等待一定时间后返回错误。 
返回: -1 
错误码:10061(由于目标机器积极拒绝,无法连接)


没有使用过bind的套接字。 
成功连接。 
产生隐式绑定,相关应用的详细资料。

name 
使用一些特殊的地址来测试。

使用远端点IP地址为INADDR_ANY测试。 
返回:-1 
错误号:10049(在其上下文中,该请求的地址无效)

使用远端点IP地址为10.1.1.255广播地址。 
返回: -1 
错误号:10060(由于连接方在一段时间后没有正确答复或连接的主机没有反应,连接尝试失败)

namelen 
同bind等需要传递地址结构长度的函数

结论

服务器必须启动listen。可以不建立本地半相关,则进行隐式绑定。客户不可以与INADDR_ANY主动相连,立即返回报错。客户不可以与广播地址连接,会等待很久,返回失败。

讨论 
10060和10061两种错误不同。 
其中10061解释为目标机器积极拒绝,返回错误很快(秒级)。 
10060的情况,返回错误需要很长时间(几十秒级)。 
此处值得深入研究,两种情况下的抓包应该不一样。

9.recvfrom

int recvfrom( SOCKET s, char FAR* buf, int len, int flags, struct sockaddr FAR* from, int FAR* fromlen );

缺少半相关 
在没有bind的套接字上面,直接recvfrom。 
返回:-1 
错误号:10022(提供了一个无效的参数)

填写from结构 
向其中填入非对端使用的地址或端口。 
正常接收,并且from内置对端地址信息。

结论 
必须先进行本地半相关,指定端口,才能够接收。 
无法通过recvfrom的地址结构限制接收的地址和端口。

10.sendto

int sendto( SOCKET s, const char FAR* buf, int len, int flags, const struct sockaddr FAR* to, int tolen );

缺少半相关 
在没有bind的套接字上面,直接sendto。 
成功。返回发送的数据个数。

不存在的对端实体

sendto到一个不存在的实体(to结构) 
返回:发送的字符数 
错误号:无

紧接着调用recvfrom 
结果:没有阻塞,直接返回 
返回:-1 
错误号:10054 (远程主机强迫关闭了一个现有的连接。)

结论

可以在未本地半相关的情况下发送数据。由系统随机选择端口。

可以向不存在的远端点发送数据,本地仍然报告发送的字节数(不管有没有人接收)。

一般情况下,没有数据的时候recvfrom会阻塞。但是当给不存在的对端发送过数据后,会收到错误报告,紧接着的一次recvfrom会立即返回失败。(后面的仍然阻塞)

思考

SOCK_DGRAM类型的服务,无法为用户确保数据的正常交付。但是通过recvfrom返回的错误,可以对发送情况作出一定的判断。

这也启示在使用SOCK_DGRAM时候的编程框架要考虑下,当recvfrom错误的时候,判断一下错误号,再进一步处理。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。