一、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. 运用pool进程池启动大量子进程

    # Pool进程池类 from multiprocessing import Pool import os import time import random def run(index): prin ...

  2. Dubbox本地 JAR包部署与安装

    Dubbox的jar包并没有部署到Maven的中央仓库中,大家在Maven的中央仓库中可以查找到Dubbo的最终版本是2.5.3 , 阿里巴巴解散了Dubbo团队后由当当网继续维护此项目,并改名为 D ...

  3. Android开发文档

    https://developer.android.com/ 用ke学上网方能打开

  4. 搭建ELK和EFK

    公司突然发下任务让我搭建elk和efk,于是做完之后写入了博客,生产环境下,亲测可用哦 搭建ELK 一共两台服务器,一个节点(logstash) 主服务器上 修改最大链接和最大打开的文件 1.临时修改 ...

  5. 【leetcode】998. Maximum Binary Tree II

    题目如下: We are given the root node of a maximum tree: a tree where every node has a value greater than ...

  6. 配置框架spring和SpringDataJpa整合----员工是爹

    <!-- 1.dataSource 配置数据库连接池--> <bean id="dataSource" class="com.mchange.v2.c3 ...

  7. python dir()详解

    Python dir() 函数 Python 内置函数 描述 dir() 函数不带参数时,返回当前范围内的变量.方法和定义的类型列表:带参数时,返回参数的属性.方法列表.如果参数包含方法__dir__ ...

  8. 那些长短不一的PCI-E插槽都有什么不一样?

    https://www.ednchina.com/news/20171121-PCI-E.html 时间:2017-11-21   目前PCI-E插槽已经成为了主板上的主力扩展插槽,除了显卡会用到P ...

  9. (转)Android Studio解决unspecified on project app resolves to an APK archive which is not supported

    出现该问题unspecified on project app resolves to an APK archive which is not supported as a compilation d ...

  10. 用MyEclipse将java文件转换成UML类图

    用MyEclipse将java文件转换成UML类图 参考: 用MyEclipse将java文件转换成UML类图 - 君临天下的博客 - CSDN博客  http://blog.csdn.net/dan ...