【写在前面:主要自用,持续更新。】
计算机网络基础
七层结构和五层结构
五层 | 七层 | 作用 | 设备 | 主要协议 |
---|---|---|---|---|
物理层 | 物理层 | 确保原始的数据可在各种物理媒体上传输 | 中继器/放大器 (Repeater) 和集线器 | - |
数据链路层 | 数据链路层 | 数据链路层为网络层提供可靠的数据传输,基本数据单位为帧 | 网桥和交换机 | 以太网协议 |
网络层 | 网络层 | 网络层负责对子网间的数据包进行路由选择。还可以实现拥塞控制、网际互连等功能,基本数据单位为IP数据报 | 路由器 | IP (Internet Protocol), ICMP (Internet Control Message Protocol, 控制报文协议), ARP(Address Resolution Protocol, 地址解析协议, 跨网络层和链路层的协议), RARP(Reverse Address Resolution Protocol, 逆地址解析协议) |
传输层 | 传输层 | 传输层负责将上层数据分段并提供端到端的、可靠的或不可靠的传输,以及端到端的差错控制和流量控制问题 | 网关 | TCP, UDP |
应用层 | 会话层-表示层-应用层 | 数据传输基本单位为报文 | - | FTP (文件传送协议), Telnet (远程登录协议), DNS (域名解析协议), SMTP (邮件传送协议), POP3 (邮局协议), HTTP (Hyper Text Transfer Protocol) |
HTTP和HTTPS
HTTP协议是"明文"传输,面临问题:数据被篡改、被监听、身份伪装。
HTTPS在HTTP的基础上加入了SSL/TLS协议,SSL/TLS依靠证书来验证服务器的身份,并为浏览器和服务器之间的通信加密。(加密传输、身份认证)
HTTPS协议的主要作用:1.建立一个信息安全通道,来保证数据传输的安全。2.确认网站的真实性。
区别:
- HTTP是超文本传输协议,信息是明文传输,HTTPS则是具有安全性的SSL/TLS加密传输协议。
- HTTP和HTTPS使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
- HTTP的连接很简单,是无状态的;HTTPS协议是由SSL/TLS+HTTP协议构建的可进行加密传输、身份认证的网络协议,比HTTP协议安全。
- HTTPS协议需要到CA申请证书,一般免费证书较少,因而需要一定费用。
HTTPS:采用对称加密和非对称加密结合的方式来保护浏览器和服务端之间的通信安全。对称加密:加密和解密都是同一个密钥。非对称加密:密钥成对出现,分为公钥和私钥,公钥和私钥之间不能互相推导,公钥加密需要私钥解密,私钥加密需要公钥解密。
SSL:在TCP协议之上,应用层之下运作,用来传输敏感信息。使用SSL连接的URL地址以https开头,而不是http。
HTTP访问过程
- 当客户在浏览器中输入网址的并按下回车,浏览器会在浏览器DNS缓存,本地DNS缓存和Hosts中寻找对应的记录,如果没有获取到则会请求DNS服务来获取对应的IP。
- 浏览器申请和服务器建立TCP连接(三次握手:SYN ACK)。
- 浏览器向服务器发送get或post请求(请求报文的方法,URL和版本)
- 浏览器向服务器发送请求报文的首部,最后发送一个空首部表示结束,如果是post还会继续提交请求报文的实体。
- 服务器应答,向浏览器发送响应报文中的版本,状态码和短语(状态码的解释,如:200 OK)。
- 服务器向浏览器发送响应报文的首部,包括自己的信息和请求的文档,最后发送一个空首部表示结束。
- 服务器向浏览器发送响应报文的实体,即用户所请求的实际数据。
- 服务器关闭和浏览器的TCP连接(四次挥手:FIN ACK)。
注:CRLF是回车换行。
HTTPS访问过程
- 浏览器使用Https的URL访问服务器(端口443),建立SSL链接。(发送浏览器支持的加密协议及版本)
- 服务器接收到SSL链接后,筛选合适的加密协议,返回CA证书(有非对称加密的公钥A)给浏览器。(服务器->浏览器:公钥A)
- 浏览器使用根证书验证证书合法性。
- 浏览器生成随机数,作为对称加密的密钥B。(浏览器:对称密钥B)浏览器使用服务器返回的公钥A,对自己生成的对称加密密钥B进行加密,得到密钥C。(浏览器:用A给B加密->密钥C)浏览器将密钥C发送给服务器。(浏览器->服务器:密钥C)
- 服务器使用自己的私钥D对接受的密钥C进行解密,得到对称密钥B,使用B给数据加密,发送加密的数据给浏览器。(服务器:用私钥D解密C->B)
- 浏览器使用密钥B解密数据,之后和服务器之间使用密钥B加密通信数据进行通信。(SSL加密层建立)
验证证书安全性过程:
- 浏览器收到服务器发送的证书后,使用本地配置的CA公钥对证书进行解密得到服务器的公钥和证书的数字签名。
- 浏览器使用CA公钥解密数字签名得到信息摘要。
- 浏览器使用签名计算方法(hash)计算当前证书信息的信息摘要,与收到的信息摘要(2中解密得到的信息摘要)作对比,如果一样,表示证书是服务器下发的,没被中间人篡改过。
注:数字证书内容包括加密后服务器的公钥、权威机构的信息、服务器域名,证书信息,证书数字签名(证书信息–[Hash函数]–>证书数字摘要–[CA私钥加密]–>数字签名),签名计算方法(hash)以及证书对应的域名。
HTTP版本
HTTP:超文本传输协议,是一个基于请求与响应、无状态的、应用层的协议,常基于TCP/IP协议传输数据。所有的WWW文件都必须遵守这个标准。设计HTTP的初衷是为了提供一种发布和接收HTML页面的方法。
版本 | 功能 | 传输层协议 |
---|---|---|
0.9 | 只有get,用于获取HTML(纯文本) | TCP |
1.0 | 请求报文与响应报文:支持首部,响应状态行,超文本,GET、HEAD、POST方法;短连接(每个请求建立一个TCP连接,完成后立刻断开) | TCP |
1.1 | 默认长连接(FIFO处理请求),分块编码传输,范围请求(允许只请求资源的某个部分),Pipelining(允许一个 TCP 连接同时发送多个请求),请求报文与响应报文:支持Host头域,增加OPTIONS、PUT、DELETE、TRACE、CONNECT方法,缓存处理 | TCP |
2 | 多路复用(二进制分帧),头部压缩(压缩相同的头部信息),随时复位(RST_STREAM:停止一个信息传输),服务器端推流(服务器预估浏览器可能需要的资源提前发送),优先权和依赖(流) | TCP |
3 | 参考 | UDP |
注:多路复用(二进制分帧):将所有传输的信息分割为更小的消息和帧,并对它们采用二进制格式的编码 ,其中HTTP1.x的首部信息会被封装到Headers帧,request body则封装到Data帧里面。HTTP 2.0 通信都在一个连接上完成,这个连接可以承载任意数量的双向数据流。相应地,每个数据流以消息的形式发送,而消息由一或多个帧组成,这些帧可以乱序发送,然后再根据每个帧首部的流标识符重新组装。HTTP/2 的每个请求都会被拆分成多个 Frame,不同请求的 Frame 组合成 Stream,Stream 是 TCP 上的逻辑传输单元,这样 HTTP/2 就达到了一条连接同时发送多条请求的目标,这就是多路复用的原理。
版本 | 问题 |
---|---|
1.0 | 连接无法复用,队头阻塞 |
1.1 | - |
2 | - |
注:队头阻塞:TCP连接在请求队列中间一个请求丢失时,会阻塞该请求之后的请求,需要等待。如一个 TCP 连接同时传输 10 个请求,其中第 1、2、3 个请求已被客户端接收,但第 4 个请求丢失,那么后面第 5 - 10 个请求都被阻塞,需要等第 4 个请求处理完毕才能被处理,这样就浪费了带宽资源。
怎样实现二进制编码
HTTP状态码
HTTP状态码(HTTP Status Code)是用以表示网页服务器HTTP响应状态的3位数字代码。
1xx:信息。
2xx:成功。200 请求成功。
3xx:重定向。301 资源被永久转移到其他URL。
4xx:客户端错误。404 请求的资源不存在。
5xx:服务端错误。500 内部服务器错误。503 服务器当前无法处理请求。522 连接超时。
TCP UDP
区别
TCP:支持可靠的面向连接服务,支持字节流传输服务,传输数据没有大小限制,支持全双工服务。
UDP:无连接、不可靠(发送方发送的数据报并不一定以相同的次序到达接收方)的传输层协议,没有提供拥塞控制机制,不提供最小延时保证,传输数据有大小限制(每个被传输的数据报限定在64KB之内)。
TCP四次挥手
- 发送方----FIN---->接收方。
发送方进入第一个等待时间:FIN-WAIT-1。 - 接收方----ACK---->发送方。
接收方收到发送方的FIN进入关闭等待阶段:CLOSE-WAIT。这个期间还可以进行数据的传输。
发送方收到接收方的第一次确认(ACK)后进入第二个等待时间:FIN-WAIT-2。 - 接收方----FIN---->发送方。
接收方进入最后确认等待:LAST-ACK。等待发送方返回的ACK。如果没有收到会进行重传。
发送方接收到FIN后会返回一个ACK。 - 发送方----ACK---->接收方。
发送方进入TIME-WAIT,默认2MSL(Maximum Segment Lifetime),这个期间不会释放连接。如果收到了重传的FIN,则会再次进入新的TIME-WAIT。直到计时器结束,释放连接。
MSL指一个片段在网络中最大的存活时间。2MSL是发送和回复一次来回所需的最大时间。如果直到2MSL发送方都没有再次收到FIN,那么认为接收方已经成功收到ACK,结束TCP连接。
IP
IP协议非常简单,仅仅提供不可靠、无连接的传送服务。
IP协议的主要功能有:无连接数据报传输、数据报路由选择和差错控制。
与IP协议配套使用实现其功能的还有地址解析协议ARP、逆地址解析协议RARP、因特网报文协议ICMP、因特网组管理协议IGMP。
IP协议
IP数据报头(20字节)
- 4位版本号:IP协议的版本,IPv4:4
- 4位头部长度:标识IP头部长度,单位:4字节。4位最大能表示15(1111),所以IP头部最长是60字节。
- 8位服务类型:优先权字段(3位)+TOS字段(4位:最小延时,最大吞吐量,最高可靠性,最小费用)+保留字段(1位:0)。TOS字段最多有一个位能置1。
- 16位总长度:整个IP数据报的长度,单位:字节。IP数据报的最大长度为65535字节。长度超过MTU会进行分片传输。
- 16位标识:唯一地标识主机发送地每一个数据报。初始值由系统随机生成,每发送一个数据报值加1。该值在数据报分片时被复制到每个分片中,因此同一个数据报的所有分片都具有相同的标识。
- 3位标志:保留位,禁止分片,更多分片。
禁止分片=1:IP数据包长度超过MTU时会丢弃该数据包并返回ICMP差错报文。
更多分片:表示还有其他该数据报的分片,数据包的最后一个分片置为0,其他分片置为1。 - 13位片偏移:分片相对原始IP数据报(仅指数据部分)的偏移。
- 8位生存时间 (TTL) :数据报到达目的地之前允许经过的路由器跳数。由发送端设置 (常见值64) 。防止数据报陷入路由循环。
每经过一个路由,TTL减1。TTL=0时,路由器将丢弃数据报,并向源端发送一个ICMP差错报文。 - 8位协议:区分上层协议,ICMP是1,TCP是6,UDP是17。
- 16位头部校验和:发送端填充,接收端CRC算法以检验IP数据报头部在传输过程中是否损坏。
- 32位源端IP地址
- 32位目的端IP地址
- 可变长的可选信息
- 记录路由:记录传输过程中经过的所有路由器的IP地址。
- 时间戳:记录每个路由器转发数据报的时间。
- 松散源路由选择:数据报发送过程必须经过指定的所有路由器。
- 严格源路由选择:数据报只能经过被指定的路由器。
注:
MTU(最大传输单元)。
封包(encode):存这个字段的时候他把实际的偏移值/8封进去。
解包(decode):解析这个字段×8得到实际偏移值。
由于这个原因,除了最后一个IP分片外,每个IP分片的数据部分的长度必须是8的整数倍(这样才能保证后面的IP分片拥有一个合适的偏移量)。
分片可能发生在发送端,也可能发生在中转路由器上。传输过程中可能多次分片,只有在最终的目标机器上,这些分片才会被内核中的IP模块重新组装。
IP地址
IP地址由网络ID和主机ID组成。同一个物理网络上的所有主机都使用同一个网络ID,网络上的一个主机对应一个主机ID。
IP地址根据网络ID的不同分为5种:
- A
- 1字节网络ID+3字节主机ID。网络ID以0开头。
- 范围1.0.0.0 到127.0.0.0。127种。
- 127.0.0.1:回环地址,表示主机本身,用于本地机器的测试。
- 0.x.x.x:代表任何地址。
- 默认子网掩码为255.0.0.0。
- B
- 2字节网络ID+2字节主机ID。网络ID以10开头。
- 范围128.0.0.0到191.255.255.255。16382种。
- 128.0.0.0和191.255.0.0为保留IP。
- C
- 3字节网络ID+1字节主机ID。网络ID以110开头。
- 范围192.0.0.0到223.255.255.255。每个网络能容纳254个主机。
- 192.0.0.0和223.255.255.0为保留IP。
- D
- 多播地址。网络ID以1110开头。
- 范围224.0.0.0到239.255.255.255。
- E
- 保留地址。网络ID以0开头。
- 范围240.0.0.0到255.255.255.254。
- 255.255.255.255用于广播地址。
注: 全0(0.0.0.0)地址对应于当前主机。全1地址(255.255.255.255)是当前子网的广播地址。
划分子网
原因:IP地址不够用了。
VLSM(可变长子网掩码)和CIDR(无类别域间路由):把传统标准的IPv4有类网络演变成一个更为高效,更为实用的无类网络。
VLSM:用于IPv4子网的划分,即把一个大的网络划分成多个小的子网。
CIDR:用于IPv4子网的聚合,主要是指路由的聚合,即路由汇总。通过CIDR可以把多个小的子网路由条目汇总成一个大网络的路由条目,以减少路由器中路由条目的数量,提高路由效率。
VLSM
基本思想:借用现有网段的主机位的最左边某几位作为子网位,划分出多个子网。
- 把原来有类网络IPv4地址中的 网络ID 部分向 主机ID 部分借位。借位的部分为 子网ID 。
- 原来的 网络ID+子网ID=新网络ID 。 子网ID 的长度决定了可以划分子网的数量。
子网掩码:用于区分IP为2级IP还是三级IP。
网络号和子网号用1表示,主机号用0表示。
简写:/数字 表示有多少位是网络号+子网号。
192.168.0.0/24 网络号占24位。
划分成两个大小一样的子网:取主机号的一位做为子网号。
192.168.0.0/25,192.168.0.128/25。
(27=128)
等长子网划分:所有子网的大小一样,子网掩码一样。
变长子网划分:子网的大小不一样。
IP与MAC (Media Access Control Address)
- IP地址是Internet协议使用的地址,而MAC地址是Ethernet协议使用的地址。
- IP地址的分配是基于网络拓朴,MAC地址的分配是基于制造商。
- MAC地址是唯一的,物理上的,不可改变的;IP地址在同一网段可以是唯一的,也可能有冲突(因为可以自己设置),动态的,虚拟的,软件的。
为什么有了MAC还要有IP?为什么有了IP还要有MAC?
MAC可以唯一标识一个设备,但当设备很多时进行路由寻址十分复杂,于是把网络划分成了多个子网,数据在转发时只需要发送到目的设备所在的子网,之后再由子网内部转发给目的设备。如果只有MAC地址,我们需要标识每个MAC地址所在的子网,无法实现。IP地址则可以知道设备所在的子网,因为对于同一个子网的设备,它的IP地址的前缀都是一样的。
由于IP地址只有在接入子网后才会产生,且在不同网络划分下会有重复,因此我们需要MAC地址来唯一标识设备。
而在转发时,我们不仅需要知道源地址(发送方)和目的地址(接收方),还需要知道下一跳的地址,这时如果在IP报文头部保存下一跳的IP也可以实现,但不利于解耦,所以在转发时,通过更改MAC地址来记录下一跳信息。
路由表 (RIB) 视为路由器的控制平面。全局路由表,通常存储在设备的动态内存,如随机存储器(Random Access Memory,RAM)中。
路由表实际上并不直接指导数据转发,路由器在执行路由查询时,查询的是FIB表,位于控制层面的路由表只是提供了路由信息而已。
转发表 (FIB) 基于 IP 包的网络前缀,判断如何进行转发。对于每一条可达的目标网络前缀,FIB 包含接口标识符和下一跳信息。 FIB 概念上类似于路由表。它维护一份 RIB 表中的转发信息镜像。
当 IP 路由从 RIB 拷贝到 FIB 时,它们的下一跳信息被明确地分析出来,包括下一跳的具体端口,以及如果到下一跳有多条路径时,每条路径的具体端口。
从A发送到D | A->B | B->C | C->D |
---|---|---|---|
源IP | A | A | A |
目的IP | D | D | D |
源MAC | A | B | C |
目的MAC | B | C | D |
下一跳 | B | C | D |
路由表(Routing Info Base,RIB)
- S:static,表示静态路由。
- C:connected,直连路由,直连可达的。
- 10.69.0.0./16和10.69.65.24/24是目的IP,需要通过172.20.0.1(下一跳IP)到达。
- 172.20.0.0/16是直连IP,该设备可以与当前设备直接传输。
- 172.20.64.23/32是local lookback(本地回路),即当前设备的IP。
转发表(Forwarding Info Base,FIB)
- vrId:VRF ID,vpn的实例id。
- prefix/mask:路由前缀/前缀长度。
- next-hop ID:对应的下一跳。参考索引表。
- vid: VLAN ID,vlan的实例号。
- interface:出接口,数据包将从哪个接口转发出去。
- mac:从接口转发出去时候应该封装的mac地址。
地址解析协议(Address Resolution Protocol,ARP)
根据IP地址获取物理地址的一个TCP/IP协议。
主机发送信息时将包含目标IP地址的ARP请求广播到网络上的所有主机,并接收返回消息,以此确定目标的物理地址;收到返回消息后将该IP地址和物理地址存入本机ARP缓存中并保留一定时间,下次请求时直接查询ARP缓存以节约资源。
路由算法与协议
- 静态:管理员手动配置
- 动态
- RIP(Routing Information Protocol)
基于距离矢量路由算法 DVR( Distance Vector Routing )。以跳数为代价单位,每个路由器周期性的与相邻路由器交换若干路由信息 <可达IP, 跳数> ,按照距离矢量算法(最短路径原则,实现最佳性)建立或更新路由表。
使用UDP的520端口来发送和接收RIP分组。
路由表项:目的地,下一跳,跳数。
跳数最大为16,表示不可达。
只适用于小型网络(传递消息经过的路由器不超过15个)。 - OSPF(Open Shortest Path First,开放最短路径优先协议)
基于Dijkstra算法。
使用IP协议号89。 - BGP
使用TCP协议的179端口号。
BGP 其着眼点不在于自动发现网络拓扑,而在于在AS之间选择最佳路由和控制路由的传播。
- RIP(Routing Information Protocol)
内部网关协议(IGP), 也称域内路由选择:使用RIP或OSPF。
外部网关协议(EGP), 也称域间路由选择:使用BGP。
进程
进程和线程
线程:程序中一个单一的顺序控制流程。每个程序都至少有一个线程,若程序只有一个线程,那就是程序本身。
进程:资源分配的基本单位,拥有一个完成的虚拟地址空间。与线程的关系:当进程发生调度时,不同的进程用有不同的虚拟地址空间,而同一进程内的不同线程共享同一地址空间。
多线程:在单个程序中同时运行多个线程完成不同的工作。
Java多线程
线程阻塞:
- sleep
线程sleep时不释放锁对象,不放弃CPU执行权。此时其他线程无法执行,被阻塞。- 恢复:到时间进入runnable状态。
- wait
线程wait时释放锁对象,放弃CPU执行权,被阻塞。- 恢复:使用notify(随机唤醒一个),notifyAll进入runnable状态。
- yield
线程yield时不释放锁对象,放弃CPU执行权给同等级或更高级的线程,线程进入就绪状态。 - join
线程join时立即进入阻塞状态,等待其他线程执行完毕,然后线程进入就绪状态。 - suspend
- 恢复:resume
进程间通信(IPC)的方式
- 无名管道( pipe ): 管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。
- 高级管道(popen): 将另一个程序当做一个新的进程在当前程序进程中启动,则它算是当前程序的子进程,这种方式我们成为高级管道方式。
- 有名管道 (named pipe) : 有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。
- 消息队列( message queue ) : 消息队列是消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
- 信号量( semophore ) : 信号量是一个计数器,用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
- 信号 ( sinal ) : 信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。
- 共享内存( shared memory ) :共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制(如信号量)配合使用,来实现进程间的同步和通信。
- 套接字( socket ) : 可用于不同机器间的进程通信。
Java 套接字
传输层建立了主机端到端(端口号)的链接。传输层为上层协议提供端到端的可靠和透明的数据传输服务,包括差错控制和流量控制等。该层向高层屏蔽了下层数据通信的细节,使高层用户看到的只是在两个传输实体间的一条主机到主机的、可由用户控制和设定的、可靠的数据通路。
网络层的IP地址可以唯一地确定Internet上的一台主机。传输层提供面向应用的可靠 (TCP) 的或不可靠 (UDP) 的数据传输机制。
- 客户端/服务器(C/S)
服务器等待客户端的请求并予以响应。客户端在需要服务时向服务器发出请求。
服务器一般始终运行,监听网络端口,一旦接受到服务请求,就会启动一个服务进程来响应,同时继续监听服务端口。 - 浏览器/服务器(B/S)
客户端在需要服务时向服务器发出请求。服务器响应后及时返回,不需要实时监听端口。
什么是socket
网络上的两个进程通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。
Socket是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元,是网络通信过程中端点的抽象表示。
Socket包含进行网络通信五元组
- 连接使用的协议
- 本地主机的IP地址:源IP
- 本地进程的协议端口:源端口
- 远地主机的IP地址:目的IP
- 远地进程的协议端口:目的端口
socket编程
Socket编程本质是接口(API),对TCP/IP的封装。
Socket的工作过程:
创建Socket => 打开连接到Socket的输入/输出流 => 按照协议对Socket进行读/写 => 关闭Socket。
socket建立连接的过程:
- 服务器监听
服务器端socket处于等待连接的状态,实时监控网络状态。
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
public class Service {
public static void main(String[] args) {
try {
// 创建套接字:可选参数 int port表示监听的端口
ServerSocket serverSocket = new ServerSocket (8090); //TCP
DatagramSocket dgSocket = new DatagramSocket(8091); //UDP
// 绑定SocketAddress: 主机号和端口 最大连接数backlog
InetSocketAddress tcpAddress=new InetSocketAddress("localhost",8090);
InetSocketAddress udpAddress=new InetSocketAddress("localhost",8091);
int backlog=10;
serverSocket.bind(tcpAddress, backlog);
dgSocket.bind(udpAddress);
// 循环监听端口
while(true) {
// 处理tcp请求
Socket socket=serverSocket.accept();
// 接收到请求创建一个线程处理请求
Thread service=new Thread(new ServerThread(socket));
service.start();
// 处理udp请求
byte[] bytes = new byte[1024];
DatagramPacket packet = new DatagramPacket(bytes, bytes.length);
dgSocket.receive(packet); // 接收udp数据包
dgSocket.send(packet); // 向客户端返回信息
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
import java.io.IOException;
import java.net.Socket;
public class ServerThread implements Runnable{
private Socket socket;
public ServerThread(Socket socket) {
this.socket=socket;
}
@Override
public void run() {
// TODO Auto-generated method stub
try {
byte[] data=new byte[1024];
socket.getInputStream().read(data); //data保存从客户端接收的请求
socket.getOutputStream().write("向客户端返回数据".getBytes());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
- 客户端请求
客户端socket提出连接请求。
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
public class Client {
public static void main(String[] args) throws UnknownHostException, IOException {
// TODO Auto-generated method stub
//tcp
Socket tcpsocket = new Socket("localhost", 8090); // 请求连接:服务器的ip+端口号
tcpsocket.getOutputStream().write("发送给服务器的数据".getBytes());
byte[] data = new byte[1024];
tcpsocket.getInputStream().read(data); //接收服务器返回的数据
tcpsocket.close();
//udp
DatagramSocket udpsocket = new DatagramSocket();
InetAddress ip=InetAddress.getByName("localhost");
DatagramPacket packet=new DatagramPacket(data, data.length, ip, 8091); //要访问的目的地址信息封装在数据包中
udpsocket.send(packet);
udpsocket.close();
}
}
其他写法
3. 连接确认
当服务器端socket监听到或接收到客户端socket的连接请求,会进行响应,建立一个新的线程把服务器端socket的描述发给客户端,一旦客户端确认了此描述,连接就建立好了。而服务器端socket继续处于监听状态,继续接收其他客户端socket的连接请求。
端口号
- 公认端口:0-1023
紧密绑定于一些服务。通常这些端口的通讯明确表明了某种服务的协议。
TCP保留端口号:HTTP 80,FTP 20/21,Te