套接字就是用来标识服务器的应用程序是由域名和端口号共同组成的
出现你说的问题可能是连接的主机不在线,或是采用的不是默认的端口号,当然也就是你输入的端口号不正确造成的,如果你知道正确的端口号,可以在域名后面输入
":端口号"就可以了
套接字允许在相同或不同机器上的两个不同进程之间进行通信。更准确地说,它是一种使用标准Unix文件描述符与其他计算机通信的方法。在Unix中,每个I/O操作都是通过写入或读取文件描述符来完成的。文件描述符只是一个与打开的文件相关联的整数,它可以是一个网络连接、一个文本文件、一个终端或其他东西。
对于程序员来说,套接字的外观和行为很像底层的文件描述符。这是因为read()和write()等命令使用套接字的方式与使用文件和管道的方式相同。
socket最初是在21BSD中引入的,随后在42BSD中被细化为当前的形式。目前大多数UNIX系统版本都提供了套接字特性。
在CS应用程序框架中使用Unix套接字。服务是一个根据客户端的请求执行某些功能的进程。大多数应用程序级协议,如FTP、SMTP和POP3,都利用套接字在客户机和服务器之间建立连接,然后进行数据交换。
有四种类型的套接字可供用户使用。前两种是最常用的,后两种很少使用。
假定进程只在相同类型的套接字之间通信,但没有限制阻止不同类型的套接字之间通信。
流套接字 ——保证在网络环境中交付。如果您通过流套接字发送三个项目“A, B, C”,它们将以相同的顺序到达-“A, B, C”。这些套接字使用TCP(传输控制协议)进行数据传输。如果无法投递,发送者将收到一个错误指示符。数据记录没有任何边界。
数据包套接字 ——不能保证在网络环境中交付。它们是无连接的,因为你不需要像在流套接字中那样有一个打开的连接——你建立一个带有目标信息的包并将它发送出去。它们使用UDP(用户数据包协议)。
原始套接字 ——这些为用户提供对底层通信协议的访问,这些协议支持套接字抽象。这些套接字通常是面向数据包的,尽管它们的确切特征取决于协议提供的接口。原始套接字不是为一般用户设计的;它们主要是为那些有兴趣开发新通信协议或访问现有协议中一些更神秘的设施的人提供的。
顺序包套接字 ——它们类似于流套接字,不同的是记录边界被保留。该接口仅作为网络系统(NS)套接字抽象的一部分提供,并且在大多数严肃的NS应用程序中非常重要。顺序包套接字允许用户对一个包或一组包操纵序列(SPP)或网络数据包协议数据报协议(IDP)的报头,通过编写一个标准头,连同任何要发送的数据,或者通过指定一个默认的报头使用所有即将输出的数据,并允许用户接收传入的数据包的报头。
套接字是支持TCP/IP网络通信的基本操作单元。
在一个套接字既保存了本机的IP地址和端口,也保存了对方主机的IP地址和端口,同时还有双方通信的协议信息。
C#的命名空间SystemNetSockets提供了Socket类。一个Socket实例包含一个本地或者一个远程的套接字信息。
Socket可以像流(Stream)一样被视为数据通道,这个通道存在于服务器和客户端之间。
数据的发送和接收均通过这个通道进行。
所以在应用程序创建Socket对象后,就可以用Send/SendTo方法将数据发送到连接的Socket中,或者使用Receive/ReceiveFrom方法接收连接的Socket数据。
图2-11显示了客户机(Client)和服务器(Server)进行通信的一般过程。
Socket类为网络通信程序提供了丰富的方法和属性。
SystemNetSockets命名空间中常用的子类有:
要通过Internet进行通信,至少需要一对套接字,其中一个运行在客户端,称之为ClientSocket,另一个运行于服务器端面,称为ServerSocket。根据连接启动的方式以及本地要连接的目标,套接字之间的连接过程可以分为三个步骤:服务器监听、客户端请求、连接确认。
服务器监听是指服务端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态。
客户端请求是由客户端的套接字提出连接请求,要连接的目标是服务器端套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器套接字的地址和端口号,然后再向服务器端套接字提出连接请求。
连接确认是当服务器端套接字监听到或者说接收到客户端套接字的连接请求时,它就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的信息发送给客户端,一旦客户端确认了此连接,连接即可建立。而服务器端继续处于监听状态,继续接收其他客户端的连接请求。
使用套接字进行数据处理有两种基本模式:同步和异步。
同步模式:
同步模式的特点是在通过Socket进行连接、接收、发送数据时,客户机和服务器在接收到对方响应前会处于阻塞状态,即一直等到收到对方请求才继续执行下面的语句。可见,同步模式只适用于数据处理不太多的场合。当程序执行的任务很多时,长时间的等待可能会让用户无法忍受。
异步模式:
异步模式的特点是在通过Socket进行连接、接收、发送操作时,客户机或服务器不会处于阻塞方式,而是利用callback机制进行连接、接收、发送处理,这样就可以在调用发送或接收的方法后直接返回,并继续执行下面的程序。可见,异步套接字特别适用于进行大量数据处理的场合。
使用同步套接字进行编程比较简单,而异步套接字编程则比较复杂。
套接字(socket)是用于网络通信的基本操作单元。简单的说就是通信的两方的一种约定,用套接字中的相关函数来完成通信过程。
套接字可以根据通信性质分类,主要分
流式套接字(sock_stream),
数据报套接字(sock_dgram)以及原始套接字(sock_raw)
数据报套接字提供了一种不可靠的、非连接的数据包通信方式。所以
数据报套接字使用udp协议,当然,winsock
2版本还支持其他协议。
要创建一个可用的套接字,需要使用下面的函数:
domain 就是指 PF_INET、PF_INET6 以及 PF_LOCAL 等,表示什么样的套接字。
type 可用的值是:
参数 protocol 原本是用来指定通信协议的,但现在基本废弃。因为协议已经通过前面两个参数指定完成。protocol 目前一般写成 0 即可。
创建出来的套接字如果需要被别人使用,就需要调用 bind 函数把套接字和套接字地址绑定调用 bind 函数的方式如下:
我们需要注意到 bind 函数后面的第二个参数是通用地址格式sockaddr addr。这里有一个地方值得注意,那就是虽然接收的是通用地址格式,实际上传入的参数可能是 IPv4、IPv6 或者本地套接字格式。bind 函数会根据 len 字段判断传入的参数 addr 该怎么解析,len 字段表示的就是传入的地址长度,它是一个可变值。
这里其实可以把 bind 函数理解成这样:
不过 BSD 设计套接字的时候大约是 1982 年,那个时候的 C 语言还没有void 的支持,为了解决这个问题,BSD 的设计者们创造性地设计了通用地址格式来作为支持 bind 和 accept 等这些函数的参数。
对于使用者来说,每次需要将 IPv4、IPv6 或者本地套接字格式转化为通用套接字格式,就像下面的 IPv4 套接字地址格式的例子一样:
对于实现者来说,可根据该地址结构的前两个字节判断出是哪种地址。为了处理长度可变的结构,需要读取函数里的第三个参数,也就是 len 字段,这样就可以对地址进行解析和判断了。
我们可以把地址设置成本机的 IP 地址,这相当告诉操作系统内核,仅仅对目标 IP 是本机 IP 地址的 IP 包进行处理。但是这样写的程序在部署时有一个问题,我们编写应用程序时并不清楚自己的应用程序将会被部署到哪台机器上。这个时候,可以利用通配地址的能力帮助我们解决这个问题。通配地址相当于告诉操作系统内核:“Hi,我可不挑活,只要目标地址是咱们的都可以。”比如一台机器有两块网卡,IP 地址分别是 202612255 和 192168111,那么向这两个 IP 请求的请求包都会被我们编写的应用程序处理。
那么该如何设置通配地址呢?
对于 IPv4 的地址来说,使用 INADDR_ANY 来完成通配地址的设置;对于 IPv6 的地址来说,使用 IN6ADDR_ANY 来完成通配地址的设置。
除了地址,还有端口。如果把端口设置成 0,就相当于把端口的选择权交给操作系统内核来处理,操作系统内核会根据一定的算法选择一个空闲的端口,完成套接字的绑定。这在服务器端不常使用。
我们来看一个初始化 IPv4 TCP 套接字的例子:
初始化创建的套接字,可以认为是一个"主动"套接字,其目的是之后主动发起请求(通过调用 connect 函数,后面会讲到)。通过 listen 函数,可以将原来的"主动"套接字转换为"被动"套接字,告诉操作系统内核:“我这个套接字是用来等待用户请求的。”当然,操作系统内核会为此做好接收用户请求的一切准备,比如完成连接队列。
listen 函数的原型是这样的:
我来稍微解释一下。第一个参数 socketfd 为套接字描述符,第二个参数 backlog,官方的解释为未完成连接队列的大小,这个参数的大小决定了可以接收的并发数目。这个参数越大,并发数目理论上也会越大。但是参数过大也会占用过多的系统资源,一些系统,比如 Linux 并不允许对这个参数进行改变。对于 backlog 整个参数的设置有一些最佳实践,这里就不展开,后面结合具体的实例进行解读
accept 这个函数的作用就是连接建立之后,操作系统内核和应用程序之间的桥梁。它的原型是:
函数的第一个参数 listensockfd 是套接字,可以叫它为 listen 套接字,因为这就是前面通过 bind,listen 一系列操作而得到的套接字。函数的返回值有两个部分,第一个部分 cliadd 是通过指针方式获取的客户端的地址,addrlen 告诉我们地址的大小,这可以理解成当我们拿起电话机时,看到了来电显示,知道了对方的号码;另一个部分是函数的返回值,这个返回值是一个全新的描述字,代表了与客户端的连接。
这里一定要注意有两个套接字描述字,第一个是监听套接字描述字 listensockfd,它是作为输入参数存在的;第二个是返回的已连接套接字描述字。
你可能会问,为什么要把两个套接字分开呢?用一个不是挺好的么?
监听套接字一直都存在,它是要为成千上万的客户来服务的,直到这个监听套接字关闭;而一旦一个客户和服务器连接成功,完成了 TCP 三次握手,操作系统内核就为这个客户生成一个 已连接套接字 ,让应用服务器使用这个已连接套接字和客户进行通信处理。如果应用服务器完成了对这个客户的服务,比如一次网购下单,一次付款成功,那么关闭的就是已连接套接字,这样就完成了 TCP 连接的释放。请注意,这个时候释放的只是这一个客户连接,其它被服务的客户连接可能还存在。最重要的是, 监听套接字 一直都处于“监听”状态,等待新的客户请求到达并服务。
前面讲述的 bind、listen 以及 accept 的过程,是典型的服务器端的过程。下面我来讲下客户端发起连接请求的过程。第一步还是和服务端一样,要建立一个套接字,方法和前面是一样的。不一样的是客户端需要调用 connect 向服务端发起请求。
客户端和服务器端的连接建立,是通过 connect 函数完成的。这是 connect 的构建函数:
函数的第一个参数 sockfd 是连接套接字,通过前面讲述的 socket 函数创建。
第二个、第三个参数 servaddr 和 addrlen 分别代表指向套接字地址结构的指针和该结构的大小。套接字地址结构必须含有服务器的 IP 地址和端口号。
客户在调用函数 connect 前不必非得调用 bind 函数,因为如果需要的话,内核会确定源 IP 地址,并按照一定的算法选择一个临时端口作为源端口。
如果是 TCP 套接字,那么调用 connect 函数将激发 TCP 的三次握手过程,而且仅在连接建立成功或出错时才返回。其中出错返回可能有以下几种情况:
1三次握手无法建立,客户端发出的 SYN 包没有任何响应,于是返回 TIMEOUT 错误。这种情况比较常见的原因是对应的服务端 IP 写错。
2客户端收到了 RST(复位)回答,这时候客户端会立即返回 CONNECTION REFUSED 错误。这种情况比较常见于客户端发送连接请求时的请求端口写错,因为 RST 是 TCP 在发生错误时发送的一种 TCP 分节。产生 RST 的三个条件是:
3客户发出的 SYN 包在网络上引起了"destination unreachable",即目的不可达的错误。这种情况比较常见的原因是客户端和服务器端路由不通。
根据不同的返回值,我们可以做进一步的排查。
我们先看一下最初的过程,服务器端通过 socket,bind 和 listen 完成了被动套接字的准备工作,被动的意思就是等着别人来连接,然后调用 accept,就会阻塞在这里,等待客户端的连接来临;客户端通过调用 socket 和 connect 函数之后,也会阻塞。接下来的事情是由操作系统内核完成的,更具体一点的说,是操作系统内核网络协议栈在工作。
下面是具体的过程:
1客户端的协议栈向服务器端发送了 SYN 包,并告诉服务器端当前发送序列号 j,客户端进入 SYNC_SENT 状态;
2服务器端的协议栈收到这个包之后,和客户端进行 ACK 应答,应答的值为 j+1,表示对 SYN 包 j 的确认,同时服务器也发送一个 SYN 包,告诉客户端当前我的发送序列号为 k,服务器端进入 SYNC_RCVD 状态;
3客户端协议栈收到 ACK 之后,使得应用程序从 connect 调用返回,表示客户端到服务器端的单向连接建立成功,客户端的状态为 ESTABLISHED,同时客户端协议栈也会对服务器端的 SYN 包进行应答,应答数据为 k+1;
4应答包到达服务器端后,服务器端协议栈使得 accept 阻塞调用返回,这个时候服务器端到客户端的单向连接也建立成功,服务器端也进入 ESTABLISHED 状态。
这一讲我们分别从服务端和客户端的角度,讲述了如何创建套接字,并利用套接字完成 TCP 连接的建立。
1为什么是三次握手
1信道不安全 保证通信需要一来一回
2客户端的来回和服务端的来回 共四次 这是最多四次
3客户端的回和服务端的来合并成一个,就是那个sync k ack j+1
4这样就是三次握手
这个问题的本质是, 信道不可靠, 但是通信双发需要就某个问题达成一致 而要解决这个问题, 无论你在消息中包含什么信息, 三次通信是理论上的最小值 所以三次握手不是TCP本身的要求, 而是为了满足"在不可靠信道上可靠地传输信息"这一需求所导致的
>
以上就是关于套接字操作尝试一个无法连接的主机怎么解决全部的内容,包括:套接字操作尝试一个无法连接的主机怎么解决、Unix Socket - 什么是socket(套接字)、C#套接字Socket类等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!