一、OSI网络七层模型

因特网是一个极为复杂的网络,分层有助于我们对网络的理解 。分层也是一种标准,为了使不同厂商的计算机能够互相通信,以便在更大范围内建立计算机网络,有必要建立一个国际范围的网络体系结构标准。

ISO组织制定了OSI网络七层模型

应用层
表示层
会话层
传输层
网络层
链路层
物理层

而因特网只用到了五层

应用层
传输层
网络层
链路层
物理层

低三层:

屏蔽底层网络的复杂性

物理层:使原始的数据比特流能在物理介质上传输。

数据链路层:通过校验、确认和反馈重发等手段,形成稳定的数据链路。(01010101)

网络层:进行路由选择和流量控制。(IP协议)

传输层:提供可靠的端口到端口的数据传输服务(TCP/UDP协议)。

高三层:

会话层:负责建立、管理和终止进程之间的会话和数据交换。

表示层:负责数据格式转换、数据加密与解密、压缩与解压缩等。

应用层:为用户的应用进程提供网络服务。

网络通信协议

二、传输层控制协议TCP

传输层控制协议(TCP)是Internet一个重要的传输层协议。TCP提供面向连接、可靠、有序、字节流传输服务。应用程序在使用TCP之前,必须先建立TCP连接。

1.TCP握手机制

检测网络是否通畅

三、用户数据报协议UDP

用户数据报协议UDP是Internet传输层协议。提供无连接、不可靠、数据尽力传输服务。

TCP和UDP比较

四、Socket

1.Scoket概述

IP地址:InetAddress

  • 唯一的标识Internet上的计算机
  • 本地回环地址(hostAddress):127.0.0.1 主机名(hostName):localhost
  • 不易记忆

端口号标识正在计算机上运行的进程(程序)

  • 不同的进程有不同的端口号
  • 被规定为一个16位的整数0~65535。其中,0~1023被预先定义的服务通信占用(如MySql占用端口3306,http占用端口80等)。除非我们需要访问这些特殊服务,否则,应该使用1024~65535这些端口中的某一个进行通信,以免发生端口冲突。

端口号与IP地址的组合得出一个网络套接字

我们知道两个进程如果需要进行通讯最基本的一个前提能能够唯一的标示一个进程,在本地进程通讯中我们可以使用PID来唯一标示一个进程,但PID只在本地唯一,网络中的两个进程PID冲突几率很大,这时候我们需要另辟它径了,我们知道IP层的ip地址可以唯一标示主机,而TCP层协议和端口号可以唯一标示主机的一个进程,这样我们可以利用ip地址+协议+端口号唯一标示网络中的一个进程。

能够唯一标示网络中的进程后,它们就可以利用socket进行通信了,什么是socket呢?我们经常把socket翻译为套接字,socket是在应用层和传输层之间的一个抽象层,它把TCP/IP层复杂的操作抽象为几个简单的接口供应用层调用已实现进程在网络中通信。

网络应用程序由成对的进程组成,这些进程通过网络相互发送报文。在一对进程之间的通信会话场景中,发起通信的进程被标识为客户,在会话开始时等待联系的进程是服务器。进程通过一个称为套接字的软件接口向网络发送报文和从网络接收报文。套接字是同一台主机内应用层与传输层之间的接口,由于该套接字是建立网络应用程序的可编程接口,因此套接字也称为应用程序和网路之间的应用程序编程接口(API)。应用程序开发者可以控制套接字在应用层端的一切,但是对该套接字的运输层端几乎没有控制权,因此网络编程实际上就是Socket编程

Internet应用最广的网络应用编程接口,实现与3种底层协议接口:

  • 数据报类型套接字SOCK_DGRAM(面向UDP接口)
  • 流式套接字SOCK_STREAM(面向TCP接口)
  • 原始套接字SOCK_RAW(面向网络层协议接口IP、ICMP等)

主要socket API及其调用过程

socket是"打开—读/写—关闭"模式的实现,以使用TCP协议通讯的socket为例,其交互流程大概如下:

2.Java中的Socket编程

客户端

public class SocketClient {

    public void client() {
Socket sc = null;
OutputStream os = null;
InputStream is = null;
try {
sc = new Socket(InetAddress.getByName("127.0.0.1"), 9092);
os = sc.getOutputStream();
os.write("我是客户端,我向你发送消息了".getBytes());
sc.shutdownOutput(); // 显式的告诉服务端发送完毕 is = sc.getInputStream();
byte[] b = new byte[30];
int len;
while ((len = is.read(b)) != -1) {
String str = new String(b, 0, len);
System.out.println(str);
} } catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
} finally { if (os != null) {
try {
os.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (is != null) {
try {
is.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (sc != null) {
try {
sc.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
} public static void main(String[] args) {
SocketClient client = new SocketClient();
client.client();
}
}

当Client程序需要从Server端获取信息及其他服务时,应创建一个Socket对象

构造函数

new Socket(InetAddress.getByName("127.0.0.1"), 9092)会打开一个套接字

一旦套接字被打开,java.net.Socket类中的getInputStream方法就会返回一个InputStream对象,该对象可以像其他任何流一样使用,接收另一端传来的数据

getOutPutStream则是输出流,可以传给另一端

套接字离不开IP地址, Java中有IP相关的类

InetAddress类没有提供公共的构造方法,而是提供了两个静态方法来获取InetAddress实例

InetAddress有如下常用方法:

服务器端

public class SocketServer {

    public void server() {
ServerSocket ss = null;
Socket s = null;
InputStream is = null;
OutputStream os = null;
try {
ss = new ServerSocket(9092);
s = ss.accept();
is = s.getInputStream();
/**
* 1、 read()方法,这个方法从输入流中读取数据的下一个字节。返回 0 到 255 范围内的 int 字节值。如果因为已经到达流末尾而没有可用的字节,则返回值 -1。 2、read(byte[] b,int
* off,int len)方法,将输入流中最多 len 个数据字节读入 byte 数组。尝试读取len 个字节,但读取的字节也可能小于该值。以整数形式返回实际读取的字节数。 3、read(byte[]
* b)方法,从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。以整数形式返回实际读取的字节数。
*/
byte[] b = new byte[30];
int len;
while ((len = is.read(b)) != -1) {
/**
* new String(bytes, offset, length) bytes为要解译的字符串; offset为要解译的第一个索引,比如从0开始就是从字符串bytes的第一个字符开始;
* length为要解译的字符串bytes的长度
*/
String str = new String(b, 0, len);
System.out.println(str);
}
os = s.getOutputStream();
os.write("我是服务端,收到了你的信息".getBytes()); } catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (os != null) {
try {
os.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (is != null) {
try {
is.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (s != null) {
try {
s.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (ss != null) {
try {
ss.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} }
} public static void main(String[] args) {
SocketServer server = new SocketServer();
server.server();
}
}

服务器需随时待命,因为不知道客户端什么时候会发来请求,此时,我们需要使用ServerSocket,对应的是java.net.ServerSocket类

构造函数

new ServerSocket(9092)建立一个监听9092接口的服务器

ss.accept()告诉程序不停的等待,直到客户端连接到这个接口。一旦有人通过网络发送了正确的连接请求,并以此连接到了端口上,该方法就返回一个表示连接已经建立的Socket对象。

可以使用这个对象来得到输入流和输出流

Java高并发网络编程(一)的更多相关文章

  1. Java高并发网络编程(四)Netty

    在网络应用开发的过程中,直接使用JDK提供的NIO的API,比较繁琐,而且想要进行性能提升,还需要结合多线程技术. 由于网络编程本身的复杂性,以及JDK API开发的使用难度较高,所以在开源社区中,涌 ...

  2. Java高并发网络编程(三)NIO

    从Java 1.4开始,Java提供了新的非阻塞IO操作API,用意是替代Java IO和Java Networking相关的API. NIO中有三个核心组件: Buffer缓冲区 Channel通道 ...

  3. Java高并发网络编程(五)Netty应用

    推送系统 一.系统设计 二.拆包和粘包 粘包.拆包表现形式 现在假设客户端向服务端连续发送了两个数据包,用packet1和packet2来表示,那么服务端收到的数据可以分为三种,现列举如下: 第一种情 ...

  4. Java高并发网络编程(二)BIO

    一.阻塞 服务器端 public class BIOServer { public static void main(String[] args) throws Exception { ServerS ...

  5. Linux下高并发网络编程

      Linux下高并发网络编程 1.修改用户进程可打开文件数限制 在Linux平台上,无论编写客户端程序还是服务端程序,在进行高并发TCP连接处理时, 最高的并发数量都要受到系统对用户单一进程同时可打 ...

  6. Linux高并发网络编程开发——10-Linux系统编程-第10天(网络编程基础-socket)

    在学习Linux高并发网络编程开发总结了笔记,并分享出来.有问题请及时联系博主:Alliswell_WP,转载请注明出处. 10-Linux系统编程-第10天(网络编程基础-socket) 在学习Li ...

  7. 从菜鸟到大神:Java高并发核心编程(连载视频)

    任何事情是有套路的,学习是如此, Java的学习,更是如此. 本文,为大家揭示 Java学习的套路 背景 Java高并发.分布式的中间件非常多,网上也有很多组件的源码视频.原理视频,汗牛塞屋了. 作为 ...

  8. select poll epoll Linux高并发网络编程模型

    0 发展历程 同步阻塞迭代模型-->多进程并发模型-->多线程并发模型-->select-->poll-->epoll-->... 1 同步阻塞迭代模型 bind( ...

  9. 尼恩 Java高并发三部曲 [官方]

    高并发 发烧友社群:疯狂创客圈(总入口) 奉上以下珍贵的学习资源: 疯狂创客圈 经典图书 : 极致经典 + 社群大片好评 < Java 高并发 三部曲 > 面试必备 + 大厂必备 + 涨薪 ...

随机推荐

  1. 【串线篇】REST风格的请求格式

    1.什么是rest 答出这两点就够了: 1.1 统一接口 rest其实是基于HTTP的,四种方式. RESTful架构风格规定,数据的元操作,即CRUD(create, read, update和de ...

  2. delphi三层DCOM架构

    DCOM架构: 服务端开发: 采用Delphi7+SQL2008 一.创建数据库和表 CREATE TABLE [dbo].[tb_Department]( [FKey] [uniqueidentif ...

  3. java模式-----单例模式

    什么是单例设计模式? 单例模式,是一种常用的软件设计模式.在它的核心结构中只包含一个被称为单例的特殊类.通过单例模式可以保证系统中,应用该模式的类一个类只有一个实例.即一个类只有一个对象实例. 类结构 ...

  4. 【leetcode】985. Sum of Even Numbers After Queries

    题目如下: We have an array A of integers, and an array queries of queries. For the i-th query val = quer ...

  5. winform 控件拖拽和缩放

    核心类: using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using ...

  6. AcWing 225. 矩阵幂求和 (矩阵快速幂+分治)打卡

    题目:https://www.acwing.com/problem/content/227/ 题意:给你n,k,m,然后输入一个n阶矩阵A,让你求  S=A+A^2+A^3.+......+A^k 思 ...

  7. AcWing 207. 球形空间产生器 (高斯消元)打卡

    有一个球形空间产生器能够在n维空间中产生一个坚硬的球体. 现在,你被困在了这个n维球体中,你只知道球面上n+1个点的坐标,你需要以最快的速度确定这个n维球体的球心坐标,以便于摧毁这个球形空间产生器. ...

  8. Linux系统之-TCP-IP链路层

    一.基本 网络层协议的数据单元是 IP 数据报 ,而数据链路层的工作就是把网络层交下来的 IP 数据报 封装为 帧(frame)发送到链路上,以及把接收到的帧中的数据取出并上交给网络层. 为达到这一目 ...

  9. mysql添加索引和sql分析

    mysql索引操作 查看索引 show indexes from students; #students为表名 mysql添加索引命令 创建索引 .PRIMARY KEY(主键索引) mysql> ...

  10. Xcode5 统计单元测试覆盖率(仅限XCTest)

    概要 通过本篇文章,你将学会如何在Xcode5下使用统计XCTest测试代码的覆盖率,以及如何快速得到测试覆盖率的图形化报表. 为什么要特别说明Xcode5下的代码覆盖率统计,原因是,以前的方法在新环 ...