0

0

Java网络编程由浅入深一图文详解

黄舟

黄舟

发布时间:2017-03-04 10:04:44

|

2815人浏览过

|

来源于php中文网

原创

本文介绍网络相关理论和简单入门的Java网络编程例子

这篇文章主要介绍计算机网络的一个整体架构和每一层的作用。

  • 计算机网络的概念

  • OSI参考模型

  • TCP/IP参考模型

    立即学习Java免费学习笔记(深入)”;

  • IP协议

  • TCP协议和端口

  • Java网络编程入门程序


计算机网络的概念

网络,就是不同节点之间通过连线互联起来的一个事物。以此类推,计算机网络,就是将不同地理位置的计算机通过通信线路连接起来的一个具有强大功能的网络系统。在这个网络中每台电脑就是一个节点。

OSI参考模型

OSI(Open System Interconnection)是由ISO组织研究的一套网络体系结构。这名字起的好
各层的名称和作用,当做了解:

名称 功能
物理层 不要理解错了,这一层不包含什么网线、电缆的物理介质。这里只是规定网线和电缆的接口类型,信号电压等。使用bit传输
数据链路层 负责两个相邻节点间的路线,以帧为单位传输。典型设备交换机(Switch)
网络层 两台计算机传输数据可能会经过很多数据链路,网络层的作用就是选择最优的路线。典型设备就是路由器
传输层 提供两个端系统的会话的建立、维护和取消传输连接的功能。使用报文传输
会话层 管理进程间的会话过程,即建立、管理、终止进程间的会话。使用报文传输
表示层 对数据的加解密、解压缩和格式转换等。
应用层 这层就是和用户的具体应用交互。例如:收发E-mail等。

TCP/IP参考模型

因为OSI网络结构分层太多过于复杂,所以TCP/IP协议横空出世。TCP/IP协议同样借助了OSI的分层思想,但是只是分为四层:

名称 功能
主机网络层 为上层提供一个访问接口
网络互联层 把IP数据包发送到目标主机。这一层使用的是IP协议,IP协议规定了数据包的格式,并且规定了为数据包寻找路由的流程。
传输层 使源主机和目标主机的进程可以进行会话。这一层定义了两种协议TCP和UDP协议。
应用层 TCP/IP模型将OSI参考模型中的会话层和表现层功能合并到应用层。

基于TCP协议的应用主要有以下几种:

•   FTP:文件传输协议,允许在网络上传输文件。
•   TELNET:虚拟终端协议,允许从主机A登入远程主机B。
•   HTTP:超文本传输协议,允许网络是传输超文本。
•   HTTPS:安全超文本传输协议。
•   POP3:允许用户访问和操作运程服务器上的邮件和邮件夹。
•   IMAP4:消息访问协议版本4,允许用户访问和操作运程服务器上的邮件和邮件夹。
•   SMTP:发送邮件的协议。

基于UDP协议的应用层协议:

•   SNMP:简单网络管理协议,为管理本地和远程的网络设备提供了一个标准化途径,是分布式环境中的集中化管理协议。
•   DNS:域名系统协议,把主机的域名转换为对应的IP地址。

IP协议

IP网络(采用IP协议的网络)中每一台主机都有唯一的IP地址,IP地址标识网络中的每个主机。IP地址是一个32位的二进制数序列。例如:192.168.3.4。IP地址与子网掩码进行与运算得到的是网络地址。如果子网掩码为255.255.255.0 那网络地址就是:192.168.3.0

发送数据包的过程

IP是面向包的协议,即数据被分成若干小数据包,然后分别传输它们。IP网络上的主机只能直接向本地网上的其他主机(也就是具有相通IP网址的主机)发送数据包。主机实际上具有两个不同性质的真实地址。主机A向同一个网络上的另一个主机B发包时,会通过地址解析协议(ARP,Address Resolution Protocol)获得对法的物理地址,然后把包给对方。ARP协议的运行机制为,主机A在网络上广播一个ARP消息:”要找地址为192.166.3.5的主机”,具有这个IP地址的主机B就会作响应,把自身的物理地址告诉A。

当主机A向另外一个网络的主机B发送包时:
主机A利用ARP协议找到本地网络上的路由器的物理地址,把包转给路由。路由器按照如下步骤处理数据包:

  1. 如果数据包的生命周期已到,则数据包被抛弃。

  2. 搜索路由表,优先搜索路由表中的主机,如果找到具有目标IP地址的主机,则将数据包发给该主机。

  3. 如果匹配主机失败,则继续搜索路由表,匹配子网的路由表,如果找到匹配的路由表,则将数据包转发给该路由器。

    Linux+PHP+MySQL案例教程
    Linux+PHP+MySQL案例教程

    本书以培养高级网站建设与管理人才为目标,内容循序渐进,由浅入深,通过大量的实例系统全面地介绍了Linux+PHP+MySQL环境下的网络后台开发技术。本书详尽分析了近30个典型案例。包括计数器、网站流量统计、留言板、论坛系统、聊天室、投票与调查、用户管理、新闻发布系统、广告轮播、购物系统等等,力求让读者通过对案例的学习,轻松掌握PHP和MySQL的编程精要,迅速掌握网络后台开发技巧。   本书适

    下载
  4. 如果匹配同子网的路由器失败,则继续搜索路由表,匹配同网络的路由器,如果找到匹配的路由器,则将数据包转发给该路由器。

  5. 如果以上匹配都失败,就搜索默认路由,如果默认路由存在,则按照默认路由发送数据包,否则丢弃数据包。
    流程图如下:
    这里写图片描述

域名

IP是一串数字没有任何意义。域名就是与IP对应的有意义的一串字符或数字。例如:www.google.com
域名和IP的对应需要一个域名解析系统来实现将域名转换成IP。DNS服务器就是就可以解决这个问题。

URL(统一资源定位符)

URL(Uniform Resource Location)是专门标识网络上资源位置而设置的一种编址方式。URL一般由3个部分组成:

应用层协议://主机IP地址或域名/资源所在路径/资源名

例如:http://www.php.cn/ 其中http 指超文本传输协议,blog.csdn.net 是Web服务器的域名,/article/details/ 是网页所在路径,54962975 这个才是相应的网页文件。

TCP协议和端口

IP协议在发送数据时,在数据传输过程中会出现各种问题。导致包丢失或包的顺序不对。TCP协议使两台主机上的进程顺利通信,不必担心包丢失或包顺序不对。TCP跟踪包顺序,如果包顺序被搞乱时按照正确的顺序进行重新组合。如果包丢失,则TCP会请求源主机重发包。

端口

TCP协议使两台主机上的进程顺利通信,但是主机不止一个进程。TCP就采取端口来区分进程。端口不是物理设备,而是用于标识进程的逻辑地址。计算机的端口范围是0到65535,其中0到1023的端口一般固定分配给一些服务。具体如下:

服务 端口 协议
文件传输服务 21 FTP
远程登录服务 23 TELENET
邮件传输服务 25 SMTP
万维网超文本传输服务 80 HTTP
访问邮件远程邮件服务 110 POP3
互联网消息存取服务 143 IMAP4
安全的超文本传输服务 443 HTTPS
安全的远程登录服务 992 TELNETS
安全互联网消息存取服务 993 IMAPS

Java网络编程入门程序

Java网络程序都建立在TCP/IP协议基础上,在应用层实现。传输层向应用层提供了套接字Socket接口,Socket封装了下层的数据传细节,应用层的程序通过Socket来建立与远程主机的连接,以及数据传输,如下图所示:
这里写图片描述

在Java中,有3种套接字类:java.net.Socketjava.net.ServerSocketjava.net.DatagramSocket 。其中SocketServerSocket 建立在TCP协议上,DatagramSocket 类建立在UDP协议基础上。我们创建EchoServer和EchoClient两个类,我们通过ServerSocketSocket来编写。

创建EchoServer类

在服务端通过一直监听端口,来接收客户程序的连接请求。在服务器程序中,先创建一个ServerSocket对象,在构造方法中指定监听的端口:

ServerSocket server = new ServerSocket(8080);

ServerSocket构造器负责在操作系统中将当前进程注册为服务进程。服务器程序调用ServerSocketaccept()方法来监听端口,等待客户端的连接,如果接收到连接,则accept()方法返回一个Socket对象,这个Socket对象与客户端的Socket对象形成了一条通信线路:

Socket socket = server.accept();

Socket提供了getInputStream()方法和getOutputStream()方法,分别返回输入流InputStream对象和输出流OutputStream对象。程序只需向输出流写入东西,就能向对方发送数据;只需从输入流读取数据,就能接收到数据。如下图:
这里写图片描述
EchoServer 类代码如下:

/**
 * 服务端 服务端类
 *
 */public class EchoServer {


    private ServerSocket serverSocket;    
    public EchoServer(int port) {        
    try {            this.serverSocket = new ServerSocket(port);
            System.out.println("start server success,start port:"+port);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }    /**
     * 获取BufferedReader包装类
     * 
     * @param socket
     * @return
     * @throws IOException
     */
    private BufferedReader getReader(Socket socket) throws IOException {        
    return new BufferedReader(new InputStreamReader(socket.getInputStream()));
    }    /**
     * 获取PrintWriter包装类,
     * 
     * @param socket
     * @return
     * @throws IOException
     */
    private PrintWriter getWriter(Socket socket) throws IOException {        
    // 每写一行自动刷新
        return new PrintWriter(socket.getOutputStream(), true);
    }    public void service() {        while (true) {
            Socket socket = null;            try {
                socket = serverSocket.accept();
                System.out.println("new connect,address is:" + socket.getInetAddress() + " port is:" + socket.getPort());
                BufferedReader reader = getReader(socket);
                PrintWriter writer = getWriter(socket);
                String msg = null;                
                while ((msg = reader.readLine()) != null) {                    
                // 读取一行
                    System.out.println("client request  msg: " + msg);
                    writer.println(echo(msg));                    
                    if ("bye".equalsIgnoreCase(msg)) {                        
                    break;
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }finally{                
            if(socket!=null){                    
            try {                        
            //关闭会话连接
                        socket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }    private String echo(String msg) {        return "get request msg is '" + msg+"'";
    }    public static void main(String[] args) {        new EchoServer(8080).service();
    }
}

EchoServer类的最主要的方法就是service()方法,它不断登录客户的连接请求。当serverSocket.accept()返回一个Socket对象时,表示与一个客户端建立了连接。

创建EchoClient

在EchoClient程序中,为了与EchoClient通信,需要先创建一个Socket对象:

String host="localhost";int port = 8080;new Socket(host, port);

host表示Server进程所在服务器的地址,port表示Server进程监听的端口。当参数host为’localhost’时,表示服务端和客户端在同一台机器上。下面是EchoClient类的源码:

public class EchoClient {
    private Socket socket;    
    public EchoClient(String host,int port){        
    try {            this.socket = new Socket(host, port);
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }    /**
     * 获取BufferedReader包装类
     * 
     * @param socket
     * @return
     * @throws IOException
     */
    private BufferedReader getReader(Socket socket) throws IOException {        
    return new BufferedReader(new InputStreamReader(socket.getInputStream()));
    }    /**
     * 获取PrintWriter包装类,
     * 
     * @param socket
     * @return
     * @throws IOException
     */
    private PrintWriter getWriter(Socket socket) throws IOException {        
    // 每写一行自动刷新
        return new PrintWriter(socket.getOutputStream(), true);
    }    public void talk(){        try {
            BufferedReader reader = getReader(socket);
            PrintWriter writer = getWriter(socket);
            BufferedReader localReader = new BufferedReader(new InputStreamReader(System.in));
            String msg = null;            
            while((msg=localReader.readLine())!=null){
                writer.println(msg);
                System.out.println("server response msg:"+reader.readLine());                
                if("bye".equalsIgnoreCase(msg)){                    
                break;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally{            
        if(socket!=null){                
        try {
                    socket.close();
                    System.out.println("has been disconnected");
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }    public static void main(String[] args) {        
    new EchoClient("localhost", 8080).talk();
    }
}

在EchoClient类中最重要的是talk()方法,该方法不断读取用户从控制台输入的字符串,然后将它发送到EchoServer,在把EchoServer返回的数据打印在控制台。如果输入’bye’字符串,就会结束与EchoServer的通信,调用socket.close()方法端口连接。
具体运行如下图,一个是服务端一个是客户端的控制台:
这里写图片描述

总结

简单介绍了一下网络的理论知识和TCP/IP协议。并使用Java实现了一个网络通信程序。

 以上就是Java网络编程由浅入深一图文详解的内容,更多相关内容请关注PHP中文网(www.php.cn)!

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
Python 序列化
Python 序列化

本专题整合了python序列化、反序列化相关内容,阅读专题下面的文章了解更多详细内容。

0

2026.02.02

AO3官网入口与中文阅读设置 AO3网页版使用与访问
AO3官网入口与中文阅读设置 AO3网页版使用与访问

本专题围绕 Archive of Our Own(AO3)官网入口展开,系统整理 AO3 最新可用官网地址、网页版访问方式、正确打开链接的方法,并详细讲解 AO3 中文界面设置、阅读语言切换及基础使用流程,帮助用户稳定访问 AO3 官网,高效完成中文阅读与作品浏览。

91

2026.02.02

主流快递单号查询入口 实时物流进度一站式追踪专题
主流快递单号查询入口 实时物流进度一站式追踪专题

本专题聚合极兔快递、京东快递、中通快递、圆通快递、韵达快递等主流物流平台的单号查询与运单追踪内容,重点解决单号查询、手机号查物流、官网入口直达、包裹进度实时追踪等高频问题,帮助用户快速获取最新物流状态,提升查件效率与使用体验。

27

2026.02.02

Golang WebAssembly(WASM)开发入门
Golang WebAssembly(WASM)开发入门

本专题系统讲解 Golang 在 WebAssembly(WASM)开发中的实践方法,涵盖 WASM 基础原理、Go 编译到 WASM 的流程、与 JavaScript 的交互方式、性能与体积优化,以及典型应用场景(如前端计算、跨平台模块)。帮助开发者掌握 Go 在新一代 Web 技术栈中的应用能力。

11

2026.02.02

PHP Swoole 高性能服务开发
PHP Swoole 高性能服务开发

本专题聚焦 PHP Swoole 扩展在高性能服务端开发中的应用,系统讲解协程模型、异步IO、TCP/HTTP/WebSocket服务器、进程与任务管理、常驻内存架构设计。通过实战案例,帮助开发者掌握 使用 PHP 构建高并发、低延迟服务端应用的工程化能力。

5

2026.02.02

Java JNI 与本地代码交互实战
Java JNI 与本地代码交互实战

本专题系统讲解 Java 通过 JNI 调用 C/C++ 本地代码的核心机制,涵盖 JNI 基本原理、数据类型映射、内存管理、异常处理、性能优化策略以及典型应用场景(如高性能计算、底层库封装)。通过实战示例,帮助开发者掌握 Java 与本地代码混合开发的完整流程。

5

2026.02.02

go语言 注释编码
go语言 注释编码

本专题整合了go语言注释、注释规范等等内容,阅读专题下面的文章了解更多详细内容。

62

2026.01.31

go语言 math包
go语言 math包

本专题整合了go语言math包相关内容,阅读专题下面的文章了解更多详细内容。

55

2026.01.31

go语言输入函数
go语言输入函数

本专题整合了go语言输入相关教程内容,阅读专题下面的文章了解更多详细内容。

27

2026.01.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 3.1万人学习

C# 教程
C# 教程

共94课时 | 8.3万人学习

Java 教程
Java 教程

共578课时 | 56万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号