socket网络通信,【计算机网络】Socket
socket网络通信,【计算机网络】Socket详细介绍
本文目录一览: socket是什么
Socket是英文“插座”的意思,它在计算机领域中指的是一种网络编程接口。
Socket技术提供了一种标准的接口,使得不同的计算机程序能够在网络上进行通信。Socket通信可以在不同的计算机之间建立网络连接,进行数据传输和通信,是实现网络通信的重要技术之一。
socket 网络编程
Socket通信可以使用不同的协议,如TCP、UDP等。其中,TCP协议是一种可靠的协议,保证数据传输的完整性和可靠性,通常用于重要数据的传输。而UDP协议则是一种不可靠的协议,传输速度更快,但可能会存在数据丢失或冗余。Socket技术被广泛应用于各种网络应用程序的开发和实现,如Web服务器、聊天软件、网络游戏等。
socket收发可以通过不同端口号
socket收发可以通过不同端口号。使用不同的端口号可以实现socket收发数据。在网络通信中,每个应用程序都可以通过不同的端口号与其他应用程序进行通信。端口号是一个16位的数字,范围从0到65535。常用的端口号已经被分配给了特定的应用程序,例如HTTP通信使用的端口号是80,HTTPS通信使用的端口号是443等。所以,socket收发可以通过不同端口号。
【计算机网络】Socket
socket进行通信的方式如下:
使用socket()系统调用能够创建一个socket,它返回一个用来在后续系统调用中引用该socket的文件描述符。
socket存在于一个通信domain中,它确定:
现在操作系统支持下列domain:
每个socket实现都至少提供了两种socket:流和数据报。这两种类型在UNIX和Internet domain中都得到了支持。
流socket提供了一个可靠的双向的字节流通信信道:
数据报socket允许数据以数据报的形式进行交换。在使用时无需与另一个socket简历连接。
传入bind()的addr比较复杂,每种socket domain都使用了不同的地址格式,如UNIX domain socket使用路径名,而Internet domain socket 使用IP地址和端口号。struct sockaddr适用于所有domain,将各种domain特定的地址结构转换成单个类型以供socket系统调用中的各个参数使用。
socket I/O 可以使用传统的read()和write()系统调用或使用一组socket特有的系统调用send() recv() sendto() recvfrom()。默认情况下,这些系统调用在I/O操作无法被立即完成时阻塞,使用fcntl() F_SETFL 操作用启用 O_NONBLOCK 打开文件状态标记可以执行非阻塞I/O
listen()系统调用将文件描述符sockfd引用的流socket标记为被动,这个socket后面会被用来接受来自其他(主动的)socket的链接。
无法再一个已连接的socket(已成功执行connect()的socket或由accept()调用返回的socket)上执行 listen()
如果服务器正忙于处理其他客户端,那么客户端的connect()可能并不能马上被accept(),这将产生一个未决的连接。
内核必须要记录所有未决的连接请求的相关信息,backlog参数允许限制这种未决连接的数量。在这个限制之内的连接请求会立即成功,之外的连接请求就会阻塞直到一个未决的连接被接受,并从未决连接队列中删除。
accept()系统调用会文件描述符sockfd引用的监听流socket上接受一个连入连接。如果在调用accept时不存在未决的连接,那么调用会阻塞直到有连接请求到达为止。
返回的结果是已连接的socket的文件描述符。addr参数指向一个用来返回socket地址的结构。
一对连接的流 socket 在两个端点之间提供了一个双向通信信道。
关闭一个连接之后,对等应用程序读取数据时将会收到文件结束(所有缓冲数据都读取之后),如果要写入数据,会收到一个SIGPIPE信号,并且系统调用返回EPIPE错误。
无法保证顺序,也无法保证能够到达。由于底层协议有时会重新传包,也可能多次到达。
尽管数据报socket是无连接的,但在数据报socket上应用connect()系统调用仍然起作用,会导致内核记录这个socket的对等socket地址。
当一个数据报socket已连接后:
在UNIX domain中,socket地址以路径名来表示,domain特定的socket地址结构的定义如下:
为将一个UNIX domain socket绑定到一个地址上,需要初始化一个sockaddr_un结构,然后将指向这个结构的一个指针作为addr参数传入bind()并将addrlen指定为这个结构的大小。
当用来绑定UNIX domain socket时,bind()会在文件系统中创建一个条目,作为socket路径名的一部分的目录需要可访问和可写。这个文件会被标记为一个socket,当再这个路径名上应用stat()时,它会在stat结构的st_mode字段中的文件类型部分返回值S_IFSOCK。
尽管UNIX domain socket是通过路径名来标识的,但这些socket上发生的I/O无须对底层设备进行操作。
有关绑定一个UNIX domain socket的注意点:
服务器流程:
客户端流程:
对于UNIX domain socket来说,数据报的传输是在内核中发生的,也是可靠的,所有消息都会按序被递送并且不会发生重复的状况。
服务器创建socket后并绑定后,进入一个无线循环,在循环中使用recvfrom()接收来自客户端的数据报,将接收到的文本转换成大小格式并使用通过recvfrom()获取的地址将转换过的文本返回给客户端。
socket文件的所有权和权限决定了哪些进程能够与这个socket进行通信
有时候让单个进程创建一对socket并将它们连接起来是比较有用的。
允许将一个UNIX domain socket绑定到一个名字上但不会在文件系统中创建的名字
要传输数据,数据链路层需要将网络层传递过来的数据报封装进被称为帧的一个一个单元。最大传输单元MTC是改层所能传输的帧大小的上限。
网络层任务:
网络层的协议是IP,IPv4使用32位地址来标识子网和主机,IPv6则使用了128位的地址。
一个裸socket(SOCK_RAW),允许程序直接与IP层进行通信,但大多数都会基于一种传输层协议之上的socket。
IP以数据报(包)的形式来传输数据。在两个主机之间发送的每一个数据报都是在网络上独立传输的,它们经过的路径可能会不同。一个IP数据报包含一个头,其大小范围为20字节到60字节。包含目标主机的地址,源地址。
一个IP实现可能会给它所支持的数据报的大小设定一个上限。所有IP实现都必须做到数据报的大小上限至少与规定的IP最小重组缓冲区大小一样大。IPv4限制值是576字节,IPv6是1500字节。
IP是一种无连接协议,并没有在相互连接的两个主机之间提供一个虚拟电路。
IP是一种不可靠的协议:尽最大可能将数据报从发送者传输给接收者,但并不保证包到达的顺序与它们被传输的顺序一致,也不保证是否重复,甚至到达。IP也美誉错误恢复。可靠性是通过使用TCP来保证的。
IPv4为IP头提供了一个校验和,这样能够检测出头中的错误,但并没有为包中所传输的数据提供任何错误检测机制。IPv6并没有为IP头提供校验和,它依赖高层协议来完成错误检测和可靠性。
IP数据报的重复使可能发生的,数据链路层采用一些技术确保可靠性以及IP数据报可能会以隧道形式穿越采用了重传机制。
IP会将数据报分段成一个个大小合适的传输单元,这些分段在到达最终目的之后会被重组成原始的数据报(每个IP分段本身就包含一个偏移量)
Socket详解
1、 Socket(套接字)概念
网络上两个程序通过一个双向的通信连接实现数据的交换,这个连接的一段称为一个 socket ,socket是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元。它是网络通信过程中端点的抽象表示,包含进行网络通信必须的五种信息:连接使用的协议,本地主机的IP地址,本地进程的协议端口,远地主机的IP地址,远地进程的协议端口。
Socket是对TCP/IP协议的封装,它把复杂的TCP/IP协议族隐藏在Socket接口后面,提供一个易用的接口,所以Socket本身并不是协议,而是一个调用接口(API)。
在一定程度可以认为Socket位于应用层和传输层之间。创建Socket连接时,可以指定使用的传输层协议,Socket可以支持不同的传输层协议(TCP或UDP),当使用TCP协议进行连接时,该Socket连接就是一个TCP连接。
2、 建立Socket连接
建立Socket连接至少需要一对套接字,其中一个运行于客户端,称为ClientSocket,另一个运行于服务器端,称为ServerSocket。
套接字之间的连接过程分为 三个步骤 :
(1)服务器监听:服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态,等待客户端的连接请求。
(2)客户端请求:指客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。
(3)连接确认:当服务器端套接字监听到或者说接收到客户端套接字的连接请求时,就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户 端,一旦客户端确认了此描述,双方就正式建立连接。而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。
3、 Socket连接与HTTP连接
由于通常情况下Socket连接就是TCP连接,因此Socket连接一旦建立,通信双方即可开始相互发送数据内容,直到双方连接断开。但在实际网络应用 中,客户端到服务器之间的通信往往需要穿越多个中间节点,例如路由器、网关、防火墙等,大部分防火墙默认会关闭长时间处于非活跃状态的连接而导致 Socket 连接断连,因此需要通过轮询告诉网络,该连接处于活跃状态。
而HTTP连接使用的是“请求—响应”的方式,不仅在请求时需要先建立连接,而且需要客户端向服务器发出请求后,服务器端才能回复数据。
4、 关于Socket长连接的心跳包
心跳包就是为了避免一个连接长时间不活跃被关闭而定时发送的一个”骚扰”数据包。
Socket本身就是长连接的,那么为什么还要心跳包呢?
理论上说,这个连接是一直保持连接的,但是实际情况中,如果中间节点出现什么故障是难以知道的。更要命的是,有的节点(防火墙)会自动把一定时间之内没有数据交互的连接给断掉。在这个时候,就需要我们的心跳包了,用于维持长连接,保活。在获知了断线之后,服务器逻辑可能需要做一些事情,比如断线后的数据清理,重新连接……当然,这个自然是要由逻辑层根据需求去做了。总的来说,心跳包主要也就是用于长连接的保活和断线处理。一般的应用下,判定时间在30-40秒比较不错。如果实在要求高,那就在6-9秒。
如果不主动关闭socket的话,系统不会自动关闭的,除非当前进程挂掉了,操作系统把占用的socket回收了才会关闭。为什么需要心跳连接?主要是为了判断当前连接是否是有效的、可被使用的。在实际应用中假设一段时间没有数据传输时候理论上说应该连接是没有问题的,但是网络复杂,中途出现问题也是常见的,网线被掐断了、对方进程挂掉了、频繁丢包等,这时候TCP连接是不可使用的,但是对于应用层并不知道,如果需知道网络情况则要很复杂的超时进行了解,TCP从底层就实现了这样的功能。心跳机制是TCP在一段时间间隔后发送确认连接端是否还存在,如果存在的话就会回传一个包确定网络有效,如果心跳包有问题,则通知上层应用当前网络有问题了。
这取决于你的server端的超时配置, 每个socket连接都是长连接,它是一个相当占用系统资源的通信管道, 如果这个长连接什么事也没干硬是要占着资源,则server端可以选择关闭这个连接,以省下资源让更多的用户连接进来。
所以,即便客户端的是采用死循环while(true)方式连到服务端,对于特定的客户端和服务端类型来说也需要一定时间间隔的心跳(告诉服务端,我还活着,虽然我没干活也没说话,但别把我关了)
socket通信—实现网络间的IO通信
图片来源
上文说到,socket可以实现数据传输的并发服务,我们可以定义多个客户端并发传输数据。
服务端需要先启动,并且while循环去接受客户端的消息:
TCP/IP(Transmission Control Protocol/Internet Protocol)即传输控制协议/网间协议,是一个工业标准的协议集,它是为广域网(WANs)设计的。
UDP(User Data Protocol,用户数据报协议)是与TCP相对应的协议。它是属于TCP/IP协议族中的一种。
Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
TCP及socket通信原理
Socket通信原理
Socket通信原理
Socket 通信原理 Socket 博客地址 Socket 是一组调用接口、是 { 应用层与 TCP/IP 协议族 } 通信的中间软件抽象层 . 调用接口是 TCP/IP 协议族的 API 函数
TCP/IP协议族包括传输层、网络层、链路层 TCP、UDP、IP、ICMP、IGMP、ARP、RARP
Socket接口将复杂的TCP/IP协议族隐藏,给用户提供一组简单的接口就是全部,让Socket去组织数据以符合指定的协议。
socket的基本操作 socket()函数、bind()函数、listen()函数、 connect()函数、accept()函数、 read()函数、write()函数、close()函数等
Unix/Linux基本哲学之一就是一切皆文件 都可以用 open –> write/read –> close 模式来操作
服务器端: socket() —> bind() —> listen() —> accept() —> read() || write() —> close() —客户端: socket() —> connect() —> wirte() || read() —> close()
服务器:创建并初始化socket实例、绑定端口号、监听端口号、阻塞等待客户端连接 客户端:创建并初始化socket实例、连接服务器、连接成功即TCP双向通信通道建立
客户端发送请求数据、服务器接受请求数据、 服务器处理请求数据、 服务器发送响应数据、客户端接受响应数据、 客户端与服务器关闭连接,此双向交互结束。
socket和http间的区别
socket和间的区别, 总结socket和的区别, 请简述和socket的区别 socket连接和连接的区别 HTTP协议:简单对象访问协议,对应于应用层 ,HTTP协议是基于TCP连接的 tcp协议: 对应于传输层 ip协议: 对应于网络层 TCP/IP是传输层协议,主要解决数据如何在网络中传输;而HTTP是应用层协议,主要解决如何包装数据。 Socket是对TCP/IP协议的封装,Socket本身并不是协议,而是一个调用接口(API),通过Socket,才能使用TCP/IP协议。 连接:连接就是所谓的短连接,即客户端向服务器端发送一次请求,服务器端响应后连接即会断掉; socket连接:socket连接就是所谓的长连接,理论上客户端和服务器端一旦建立起连接将不会主动断掉;但是由于各种环境因素可能会是连接断开,比如说:服务器端或客户端主机down了,网络故障,或者两者之间长时间没有数据传输,网络防火墙可能会断开该连接以释放网络资源。
最大区别socket是网络层,是应用成。。 socket是一个程序组件,它支持TCP,UDP等网络通讯协议,也就是通过socket这个东西你可以和任何互联网或局域网上的计算机通讯。。。TCP,UDP是一个网络层协议,网络层协议不管你发的内容是啥,他只负责把...
和socket的区别 是属于应用层的网络协议,应用广泛,目前我们的webservice服务网络中传输就是通过HTTP协议。 socket是属于网络层的,可以编程tcp或者UDP协议传输数据,协议其实就是基于tcp协议的。
HTTP 和 Socket 的区别 1、HTTP:超文本传输协议,首先它是一个协议,并且是基于TCP/IP协议基础之上的应用层协议。 TCP/IP协议是传输层协议,主要解决数据如何在网络中传输,HTTP是应用层协议,主要解决如何包装数据。HTTP协议详细规定了浏览器与服务器之间相互通信的规则,是万维网交换信息的基础。HTTP是基于请求-响应形式并且是短连接,并且是无状态的协议。针对其无状态特性,在实际应用中又需要有状态的形式,因此一般会通过session/cookie技术来解决此问题。 2、Socket:Socket不属于协议范畴,而是一个调用接口(API),Socket是对TCP/IP协议的封装,通过调用Socket,才能使用TCP/IP协议。 Socket连接是长连接,理论上客户端和服务器端一旦建立连接将不会主动断开此连接。Socket连接属于请求-响应形式,服务端可主动将消息推送给客户端。
socket和的区别 socket属于传输层;HTTP属性应用层协议; HTTP使用Socket TCP进行传输; 打个比方:Socket是车,而HTTP是坐在车里的人
你好楼主#10086# jsp页面中通过get方式发送请求给后台服务,可能会出现乱码,需要做URL传递参数内容编码,你也可以来后盾网一流导师指导你如: URLEncoder.encode("北京","GBK"); GBK为编码字符集,也可以为UTF-8只要能解析中文都可以。
HTTP和Socket连接的区别 是短连接,直接工作在应用层,终端发送请求就联通,服务请求完就断开。 socket是长连接,将tcp/ip协议封装后传输,安全性高,而且两端终端联通后一直连接。
和socket通信的区别 HTTP协议:简单对象访问协议,对应于应用层 ,HTTP协议是基于TCP连接的 tcp协议: 对应于传输层 ip协议: 对应于网络层 TCP/IP是传输层协议,主要解决数据如何在网络中传输;而HTTP是应用层协议,主要解决如何包装数据。 Socket是对TCP/IP协议的封装,Socket本身并不是协议,而是一个调用接口(API),通过Socket,才能使用TCP/IP协议。 连接:连接就是所谓的短连接,即客户端向服务器端发送一次请求,服务器端响应后连接即会断掉; socket连接:socket连接就是所谓的长连接,理论上客户端和服务器端一旦建立起连接将不会主动断掉;但是由于各种环境因素可能会是连接断开,比如说:服务器端或客户端主机down了,网络故障,或者两者之间长时间没有数据传输,网络防火墙可能会断开该连接以释放网络资源。
sockettcp通信,跑一段时间后,延迟很严重
一、网络自身问题您想要连接的目标网站所在的服务器带宽不足或负载过大。处理办法很简单,请换个时间段再上或者换个目标网站。
二、网线问题导致网速变慢表现为:一种情况是刚开始使用时网速就很慢;另 一种情况则是开始网速正常,但过了一段时间后,网速变慢。后一种情况在台式电脑上表现非常明显,但用笔记本电脑检查时网速却表现为正常。对于这一问题本人 经多年实践发现,因不按正确标准制作的网线引起的网速变慢还同时与网卡的质量有关。一般台式计算机的网卡的性能不如笔记本电脑的,因此,在用交换法排除故 障时,使用笔记本电脑检测网速正常并不能排除网线不按标准制作这一问题的存在。我们现在要求一律按T586A、T586B标准来压制网线,在检测故障时不 能一律用笔记本电脑来代替台式电脑。
三、网络中存在回路导致网速变慢当网络涉及的节点数不是很多、结构不是很复杂时,这种现象一般很少发生。但在一些比较复杂的网络中,经常有多余的备用线路,如无意间连上时 会构成回路。比如网线从网络中心接到计算机一室,再从计算机一室接到计算机二室。同时从网络中心又有一条备用线路直接连到计算机二室,若这几条线同时接 通,则构成回路,数据包会不断发送和校验数据,从而影响整体网速。这种情况查找比较困难。为避免这种情况发生,要求我们在铺设网线时一定养成良好的习惯: 网线打上明显的标签,有备用线路的地方要做好记载。当怀疑有此类故障发生时,一般采用分区分段逐步排除的方法。
四、网络设备硬件故障引起的广播风暴而导致网速变慢作为发现未知设备的主要手段,广播在网络中起着非常重要的作用。然而,随着网络中计算机数量的增多,广播包的数量会急剧增加。当广播包的数 量达到30%时,网络的传输效率将会明显下降。当网卡或网络设备损坏后,会不停地发送广播包,从而导致广播风暴,使网络通信陷于瘫痪。因此,当网络设备硬 件有故障时也会引起网速变慢。当怀疑有此类故障时,首先可采用置换法替换集线器或交换机来排除集线设备故障。如果这些设备没有故障,关掉集线器或交换机的 电源后,DOS下用 “Ping”命令对所涉及计算机逐一测试,找到有故障网卡的计算机,更换新的网卡即可恢复网速正常。网卡、集线器以及交换机是最容易出现故障引起网速变慢 的设备。
五、网络中某个端口形成了瓶颈导致网速变慢实际上,路由器广域网端口和局域网端口、交换机端口、集线器端口和服务器网卡等都可能成为网络瓶颈。当网速变慢时,我们可在网络使用高峰时 段,利用网管软件查看路由器、交换机、服务器端口的数据流量;也可用 Netstat命令统计各个端口的数据流量。据此确认网络数据流通瓶颈的位置,设法增加其带宽。具体方法很多,如更换服务器网卡为100M或1000M、 安装多个网卡、划分多个VLAN、改变路由器配置来增加带宽等,都可以有效地缓解网络瓶颈,可以最大限度地提高数据传输速度。
到底什么是Socket?
本系列文章前面那些主要讲解的是计算机网络的理论基础,但对于即时通讯IM这方面的应用层开发者来说,跟计算机网络打道的其实是各种API接口。
本篇文章就来聊一下网络应用程序员最熟悉的Socket这个东西,抛开生涩的计算机网络理论,从应用层的角度来理解到底什么是Socket。
对于 Socket 的认识,本文将从以下几个方面着手介绍:
1) Socket 是什么;
2) Socket 是如何创建的;
3) Socket 是如何连接的;
4) Socket 是如何收发数据的;
5) Socket 是如何断开连接的;
6) Socket 套接字的删除等。
特别说明: 本文中提到的“Socket”、“网络套接字”、“套接字”,如无特殊指明,指的都是同一个东西哦。
Socket 是什么
一个数据包经由应用程序产生,进入到协议栈中进行各种报文头的包装,然后操作系统调用网卡驱动程序指挥硬件,把数据发送到对端主机。
我们大家知道,协议栈其实是位于操作系统中的一些协议的堆叠,这些协议包括 TCP、UDP、ARP、ICMP、IP等。即时通讯开发可以找蔚可云开发。
通常某个协议的设计都是为了解决特定问题的,比如:
1) TCP 的设计就负责安全可靠的传输数据;
2) UDP 设计就是报文小,传输效率高;
3) ARP 的设计是能够通过 IP 地址查询物理(Mac)地址;
4) ICMP 的设计目的是返回错误报文给主机;
5) IP 设计的目的是为了实现大规模主机的互联互通。
应用程序比如浏览器、电子邮件、文件传输服务器等产生的数据,会通过传输层协议进行传输。而应用程序是不会和传输层直接建立联系的,而是有一个能够连接应用层和传输层之间的套件,这个套件就是 Socket 。
应用程序的下面: 就是操作系统内部,操作系统内部包括协议栈,协议栈是一系列协议的堆叠。
操作系统下面: 就是网卡驱动程序,网卡驱动程序负责控制网卡硬件,驱动程序驱动网卡硬件完成收发工作。
在操作系统内部有一块用于存放控制信息的存储空间,这块存储空间记录了用于控制通信的控制信息。其实这些控制信息就是 Socket 的实体,或者说存放控制信息的内存空间就是Socket的实体。
这里大家有可能不太清楚所以然,所以我用了一下 netstat 命令来给大伙看一下Socket是啥玩意。
Socket 是如何创建的
通过上节的讲解,现在你可能对 Socket 有了一个基本的认识,先喝口水,休息一下,让我们继续探究 Socket。
现在我有个问题, Socket 是如何创建的呢?
Socket 是和应用程序一起创建的。
应用程序中有一个 socket 组件,在应用程序启动时,会调用 socket 申请创建Socket,协议栈会根据应用程序的申请创建Socket:首先分配一个Socket所需的内存空间,这一步相当于是为控制信息准备一个容器,但只有容器并没有实际作用,所以你还需要向容器中放入控制信息;如果你不申请创建Socket所需要的内存空间,你创建的控制信息也没有地方存放,所以分配内存空间,放入控制信息缺一不可。至此Socket的创建就已经完成了。
Socket创建完成后,会返回一个Socket描述符给应用程序,这个描述符相当于是区分不同Socket的号码牌。根据这个描述符,应用程序在委托协议栈收发数据时就需要提供这个描述符。
Socket 是如何连接的
Socket创建完成后,最终还是为数据收发服务的。但是,在数据收发之前,还需要进行一步“连接”(术语就是 connect),建立连接有一整套过程。
实际上这个“连接”是应用程序通过 TCP/IP 协议标准从一个主机通过网络介质传输到另一个主机的过程。
Socket刚刚创建完成后,还没有数据,也不知道通信对象。
在这种状态下: 即使你让客户端应用程序委托协议栈发送数据,它也不知道发送到哪里。所以浏览器需要根据网址来查询服务器的 IP 地址,查询到目标主机后,再把目标主机的 IP 告诉协议栈。至此,客户端这边就准备好了。
在服务器上: 与客户端一样也需要创建Socket,但是同样的它也不知道通信对象是谁,所以我们需要让客户端向服务器告知客户端的必要信息: IP 地址和端口号 。
现在通信双方建立连接的必要信息已经具备,可以开始“连接”过程了。
首先: 客户端应用程序需要调用 Socket 库中的connect方法,提供 socket 描述符和服务器 IP 地址、端口号。
以下是connect的伪码调用:
1connect(
、
)
这些信息会传递给协议栈中的 TCP 模块,TCP 模块会对请求报文进行封装,再传递给 IP 模块,进行 IP 报文头的封装,然后传递给物理层,进行帧头封装。
之后通过网络介质传递给服务器,服务器上会对帧头、IP 模块、TCP 模块的报文头进行解析,从而找到对应的Socket。
Socket收到请求后,会写入相应的信息,并且把状态改为正在连接。
请求过程完成后: 服务器的 TCP 模块会返回响应,这个过程和客户端是一样的
Socket 是如何收发数据的
当控制流程上节中的连接过程回到应用程序之后,接下来就会直接进入数据收发阶段。
数据收发操作是从应用程序调用 write 将要发送的数据交给协议栈开始的,协议栈收到数据之后执行发送操作。
协议栈不会关心应用程序传输过来的是什么数据,因为这些数据最终都会转换为二进制序列,协议栈在收到数据之后并不会马上把数据发送出去,而是会将数据放在发送缓冲区,再等待应用程序发送下一条数据。
为什么收到数据包不会直接发送出去,而是放在缓冲区中呢?
因为只要一旦收到数据就会发送,就有可能发送大量的小数据包,导致网络效率下降(所以协议栈需要将数据积攒到一定数量才能将其发送出去)。
至于协议栈会向缓冲区放多少数据,这个不同版本和种类的操作系统有不同的说法。
服务器ip地址和端口号>
描述符>
疯狂Java讲义:使用Socket进行通信[2]
程序清单 codes/ / /Client java
public class Client
{
public static void main(String[] args)
throws IOException
{
Socket socket = new Socket( )
//将Socket对应的输入流包装成BufferedReader
BufferedReader br = new BufferedReader(
new InputStreamReader(socket getInputStream()))
//进行普通IO操作
String line = br readLine()
System out println( 来自服务器的数据 + line)
//关闭输入流 socket
br close()
socket close()
}
}
上面程序中粗体字代码是使用ServerSocket和Socket建立网络连接的代码 斜体字代码是通过Socket获取输入流 输出流进行通信的代码 通过程序不难看出 一旦使用ServerSocket Socket建立网络连接之后 程序通过网络通信与普通IO并没有太大的区别
先运行上面程序中的Server类 将看到服务器一直处于等待状态 因为服务器使用了死循环来接受来自客户端的请求 再运行Client类 将可看到程序输出 来自服务器的数据 您好 您收到了服务器的新年祝福! 这表明客户端和服务器端通信成功
上面程序为了突出通过ServerSocket和Socket建立连接 并通过底层IO流进行通信的主题 程序没有进行异常处理 也没有使用finally块来关闭资源
实际应用中 程序可能不想让执行网络连接 读取服务器数据的进程一直阻塞 而是希望当网络连接 读取操作超过合理时间之后 系统自动认为该操作失败 这个合理时间就是超时时长 Socket对象提供了一个setSoTimeout(int timeout)来设置超时时长 如下的代码片段所示
Socket s = new Socket( )
//设置 秒之后即认为超时
s setSoTimeout( )
当我们为Socket对象指定了超时时长之后 如果在使用Socket进行读 写操作完成之前已经超出了该时间限制 那么这些方法就会抛出SocketTimeoutException异常 程序可以对该异常进行捕捉 并进行适当处理 如下代码所示
try
{
//使用Scanner来读取网络输入流中的数据
Scanner scan = new Scanner(s getInputStream())
//读取一行字符
String line = scan nextLine()
…
}
//捕捉SocketTimeoutException异常
catch(SocketTimeoutException ex)
{
//对异常进行处理
…
}
假设程序需要为Socket连接服务器时指定超时时长 即经过指定时间后 如果该Socket还未连接到远程服务器 则系统认为该Socket连接超时 但Socket的所有构造器里都没有提供指定超时时长的参数 所以程序应该先创建一个无连接的Socket 再调用Socket的connect()方法来连接远程服务器 而connect方法就可以接受一个超时时长参数 如下代码所示
//创建一个无连接的Socket
Socket s = new Socket()
//让该Socket连接到远程服务器 如果经过 秒还没有连接到 则认为连接超时
s connconnect(new InetAddress(host port) )
返回目录 疯狂Java讲义
编辑推荐
Java程序性能优化 让你的Java程序更快 更稳定
新手学Java 编程
Java程序设计培训视频教程
lishixinzhi/Article/program/Java/hx/201311/27265