草庐IT

socket编程之connect()

飒飒ai 2023-11-12 原文

5 connect()

connect() 系统调用将文件描述符 sockfd 引用的套接字连接到 addr 指定的地址。

2.1 包含头文件

#include <sys/types.h>        
#include <sys/socket.h>

2.2 函数主体

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

参数解释:

  • int sockfd

​ socket()函数返回的未被使用的文件描述符

  • const struct sockaddr *addr

​ 该地址为所要连接的socket的地址,connect() 系统调用将文件描述符 sockfd 引用的套接字连接到 addr 指定的地址。

​ 如果套接字 sockfd 的类型为 SOCK_DGRAM,则 addr 是默认情况下数据报发送到的地址,也是接收数据报的唯一地址。如果套接字的类型为 SOCK_STREAM 或 SOCK_SEQPACKET,则此调用将尝试与绑定到 addr 指定的地址的套接字建立连接。通常,基于连接的协议套接字可能只成功连接()一次;无连接协议(例如UDP数据报)套接字可以多次使用 connect() 来更改其关联。

  • socklen_t addrlen

​ addrlen 参数指定 addr 的大小。

2.3 返回值

如果连接成功,则返回0;出错时,返回-1,错误类型如下:

错误类型解释
EACCES, EPERM用户尝试连接到广播地址,但未启用套接字广播标志,或者由于本地防火墙规则,连接请求失败。
EACCES(本地套接字)对套接字文件的写入权限被拒绝,或者对路径前缀中的某个目录的搜索权限被拒绝。
EADDRINUSE本地地址已在使用中。
EAFNOSUPPORT传递的地址其sa_family字段中不正确。
EAGAIN路由缓存中的条目不足。
EALREADY套接字为非阻塞套接字,且上一次尝试连接还未完成。
EBADFsockfd不是有效的文件描述符。
ECONNREFUSED流套接字上的 connect() 发现没有在监听的远程地址。
EFAULT套接字结构地址位于用户的地址空间之外。
EINTR本次系统调用被捕获的信号中断。
EISCONN套接字已连接。
ENETUNREACH网络无法访问。
EPROTOTYPE套接字类型不支持请求的通信协议。例如,尝试将 UNIX 域数据报套接字连接到流套接字时,可能会发生此错误。
ETIMEDOUT尝试连接时超时。 服务器可能太忙,无法接受新连接。 对于 IP 套接字,在服务器上启用 syncookie 时,超时可能很长。

2.4 小结

介绍完connect()函数之后,socket编程的五个基本函数便已经全部介绍完毕,基于这五个函数的两个或多个套接字便可以正常建立连接,进行读写操作,读写操作用到的函数将在后面的小节中继续总结更新。此处,先对服务端和客户端建立连接的过程进行总结。

我们创建的socket的数据结构如下图,每个进程都会维护一个这样的文件描述符表。

服务端与客户端建立连接的流程如下:

  • 服务端:socket()—bind()—listen()—accept()(阻塞…)
  • 客户端:socket()—connect()(阻塞…)

在客户端调用connect()尝试连接服务端时,双方三次握手建立连接的流程如下:

对上图进一步补充说明:

  • 客户端调用connect()时,双方开始三次握手建立连接,建立连接流程如下:

    • 客户端调用connect()后阻塞,向服务端发送SYN J包,此时客户端进入SYN_SENT状态,等待服务端发送ACK+SYN
    • 服务端收到SYN报文后,进入SYN_RCVD状态,发送ACK J+1,SYN K给客户端,发送成功后进入ESTABLISTED状态。
    • 客户端收到ACK+SYN后,connect()返回,进入ESTABLISTED状态,向服务端发送ACK K+1。
    • 服务端收到ACK包后,accept()函数返回,返回值为监听socket维护的第一个队列中的第一个socket。
  • 监听套接字会维护两个连接队列,第一个为进入ESTABLISTED状态的套接字队列,第二个为ESTABLISTED状态之前的套接字队列。可以通过“netstat -an”命令查看主机目前所维护的来连接。

  • 服务端和客户端socket初始化步骤为何有区别:

    • 服务端,顾名思义用来提供服务,不同的端口提供不同的服务,因此需要绑定唯一的端口来表明该服务的地址,这样客户端才可以找到该服务的位置。
    • 客户端,建立连接也需要一个端口,但是并不需要固定一个端口,因此默认有系统随机分配。同时面向连接的TCP数据报中会包含主机与目的主机的IP和端口,因此,不需要再应用层使用bind()进行绑定。

函数的简单实战可以通过这个项目:代码传送门

有关socket编程之connect()的更多相关文章

  1. ruby-openid:执行发现时未设置@socket - 2

    我在使用omniauth/openid时遇到了一些麻烦。在尝试进行身份验证时,我在日志中发现了这一点:OpenID::FetchingError:Errorfetchinghttps://www.google.com/accounts/o8/.well-known/host-meta?hd=profiles.google.com%2Fmy_username:undefinedmethod`io'fornil:NilClass重要的是undefinedmethodio'fornil:NilClass来自openid/fetchers.rb,在下面的代码片段中:moduleNetclass

  2. ruby - 寻找通过阅读代码确定编程语言的ruby gem? - 2

    几个月前,我读了一篇关于ruby​​gem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:

  3. 网络编程套接字 - 2

    网络编程套接字网络编程基础知识理解源`IP`地址和目的`IP`地址理解源MAC地址和目的MAC地址认识端口号理解端口号和进程ID理解源端口号和目的端口号认识`TCP`协议认识`UDP`协议网络字节序socket编程接口`sockaddr``UDP`网络程序服务器端代码逻辑:需要用到的接口服务器端代码`udp`客户端代码逻辑`udp`客户端代码`TCP`网络程序服务器代码逻辑多个版本服务器单进程版本多进程版本多线程版本线程池版本服务器端代码客户端代码逻辑客户端代码TCP协议通讯流程TCP协议的客户端/服务器程序流程三次握手(建立连接)数据传输四次挥手(断开连接)TCP和UDP对比网络编程基础知识

  4. ruby - 我正在学习编程并选择了 Ruby。我应该升级到 Ruby 1.9 吗? - 2

    我完全不是程序员,正在学习使用Ruby和Rails框架进行编程。我目前正在使用Ruby1.8.7和Rails3.0.3,但我想知道我是否应该升级到Ruby1.9,因为我真的没有任何升级的“遗留”成本。缺点是什么?我是否会遇到与普通gem的兼容性问题,或者甚至其他我不太了解甚至无法预料的问题? 最佳答案 你应该升级。不要坚持从1.8.7开始。如果您发现不支持1.9.2的gem,请避免使用它们(因为它们很可能不被维护)。如果您对gem是否兼容1.9.2有任何疑问,您可以在以下位置查看:http://www.railsplugins.or

  5. ruby - 如何以编程方式删除实例上的 "singleton information"以使其编码(marshal)? - 2

    我创建了一个由于“在运行时执行的单例元类定义”而无法编码的对象(这段代码的描述是否正确?)。这是通过以下代码执行的:#defineclassXthatmyusesingletonclassmetaprogrammingfeatures#throughcallofmethod:break_marshalling!classXdefbreak_marshalling!meta_class=class我该怎么做才能使对象编码正确?是否可以从对象instance_of_x的classX中“移除”单例组件?我真的需要一个建议,因为我们的一些对象需要通过Marshal.dump序列化机制进行缓存。

  6. Ruby 元编程问题 - 2

    我正在查看Ruby日志记录库Logging.logger方法并从sourceatgithub提出问题与这段代码有关:logger=::Logging::Logger.new(name)logger.add_appendersappenderlogger.additive=falseclass我知道类 最佳答案 这实际上删除了方法(当它实际被执行时)。这是确保close不会被调用两次的保障措施。看起来好像有嵌套的“class 关于Ruby元编程问题,我们在StackOverflow上找到一

  7. ruby - Paperclip:以编程方式分配图像并设置其名称 - 2

    使用Paperclip,我想从这样的URL抓取图像:require'open-uri'user.photo=open(url)问题是我最后得到一个像“open-uri20110915-4852-1o7k5uw”这样的文件名。有什么方法可以更改user.photo上的文件名?作为一个额外的变化,Paperclip将我的文件存储在S3上,所以如果我可以在初始分配中设置我想要的文件名就更好了,这样图像就会上传到正确的S3key。像这样:user.photo=open(url),:filename=>URI.parse(url).path 最佳答案

  8. ruby - 如何以编程方式检查证书是否已被吊销? - 2

    我正在开发一个xcode自动构建系统。在执行一些预构建验证时,我想检查指定的证书文件是否已被撤销。我了解securityverify-cert验证其他证书属性但不验证吊销。我如何检查撤销?我正在用Ruby编写构建系统,但我对任何语言的想法都持开放态度。我阅读了这个答案(Openssl-Howtocheckifacertificateisrevokedornot),但指向底部的链接(DoesOpenSSLautomaticallyhandleCRLs(CertificateRevocationLists)now?)进入的Material对我的目的来说有点过于复杂(用户上传已撤销的证书是一

  9. ruby HTTPClient : How to use persistent connections? - 2

    如何通过HTTPClient使用持久HTTP连接?发送HTTP请求时是否只是设置KeepAlive的问题?文档指出支持持久连接,但没有告诉我们如何使用它们。 最佳答案 是availableinNet::HTTP如文档中所写,Net::HTTP.startimmediatelycreatesaconnectiontoanHTTPserverwhichiskeptopenforthedurationoftheblock.Theconnectionwillremainopenformultiplerequestsintheblockift

  10. ruby - 如何保持我不常用的编程语言技能 - 2

    关闭。这个问题是off-topic.它目前不接受答案。想改进这个问题吗?Updatethequestion所以它是on-topic用于堆栈溢出。关闭11年前。Improvethisquestion我不经常使用ruby​​-通常它加起来相当于每两个月或更长时间编写一次脚本。我的大部分编程都是使用C++进行的,这与ruby​​有很大不同。由于我与ruby​​之间的差距如此之大,我总是忘记语言的基本方面(比如解析文本文件和其他简单的东西)。我想每天练习一些基本的东西,我想知道是否有一些我可以订阅的网站,并且会向我发送当天的Ruby问题或类似的东西。有人知道这样的站点/Internet服务吗?

随机推荐