Web全栈~28.网络编程

上一期

前言

网络编程往往都是困难、复杂,而且极易出错的。程序员必须掌握与网络有关的大量细节,有时甚至要对硬件有深刻的认识。一般地,我们需要理解网络协议中不同的“层”(Layer)。而且对于每个连网库,一般都包含了数量众多的函数,分别涉及信息块的连接、打包和拆包;这些块的来回运输;以及握手等等。这是一项令人痛苦的工作。但是,连网本身的概念并不是很难。我们想获得位于其他地方某台机器上的信息,并把它们移到这儿;或者相反。这与读写文件非常相似,只是文件存在于远程机器上,而且远程机器有权决定如何处理我们请求或者发送的数据。

Java 最出色的一个地方就是它的“无痛苦连网”概念。有关连网的基层细节已被尽可能地提取出去,并隐藏在JVM 以及Java 的本机安装系统里进行控制。我们使用的编程模型是一个文件的模型;事实上,网络连接(一个“套接字”)已被封装到系统对象里,所以可象对其他数据流那样采用同样的方法调用。除此以外,在我们处理另一个连网问题——同时控制多个网络连接——的时候,Java 内建的多线程机制也是十分方便的。

当然,为了分辨来自别处的一台机器,以及为了保证自己连接的是希望的那台机器,必须有一种机制能独一无二地标识出网络内的每台机器。早期网络只解决了如何在本地网络环境中为机器提供唯一的名字。但Java面向的是整个因特网,这要求用一种机制对来自世界各地的机器进行标识。为达到这个目的,我们采用了IP(互联网地址)的概念。

InetAddress类和InetSocketAddress 类的使用

   public static void main(String[] args) throws IOException {//认识本机的IP地址InetAddress ia = InetAddress.getLocalHost();System.out.println(ia);System.out.println(ia.getHostName());System.out.println(ia.getHostAddress());byte[] buf = ia.getAddress();System.out.println(buf.length);System.out.println(Arrays.toString(buf));//认识百度的IP地址InetAddress ia2 = InetAddress.getByName("www.baidu.com");System.out.println(ia2);System.out.println(ia2.getHostAddress());System.out.println(Arrays.toString(ia2.getAddress()));InetAddress addr = InetAddress.getByName("www.baidu.com");int port = 4321;InetSocketAddress isa = new InetSocketAddress(addr, port);System.out.println(isa);System.out.println(isa.getAddress());System.out.println(isa.getPort());}

服务器和客户机

网络最基本的精神就是让两台机器连接到一起,并相互“交谈”或者“沟通”。一旦两台机器都发现了对方,就可以展开一次令人愉快的双向对话。服务器和客户机它们之间的区别只有在客户机试图同服务器连接的时候才显得非常明显。一旦连通,就变成了一种双向通信,谁来扮演服务器或者客户机便显得不那么重要了。所以服务器的主要任务是侦听建立连接的请求,这是由我们创建的特定服务器对象完成的。而客户机的任务是试着与一台服务器建立连接,这是由我们创建的特定客户机对象完成的。一旦连接建好,那么无论在服务器端还是客户机端,连接只是魔术般地变成了一个 IO数据流对象。从这时开始,我们可以象读写一个普通的文件那样对待连接。所以一旦建好连接,我们只需使用自己熟悉的 IO 命令即可。这正是Java连网最方便的一个地方。

简单的网络连接案例

客户端
public class ClientTest {public static void main(String[] args) throws IOException {//localhost 表示 127.0.0.1 也就是主机自身  8080表示端口号  一般的web项目默认端口号是8080Socket socket = new Socket(InetAddress.getByName("localhost"),8080);//向服务器端发出一个请求OutputStream outputStream = socket.getOutputStream();DataOutputStream dataOutputStream = new DataOutputStream(outputStream);dataOutputStream.writeUTF("客户端给服务器端发送了一个请求");//释放资源outputStream.close();dataOutputStream.close();}
}
服务器端
public class ServerTest {public static void main(String[] args) throws IOException {System.out.println("----------------服务器已启动----------------");//监听客户端ServerSocket serverSocket = new ServerSocket(8080);Socket socket = serverSocket.accept();//接受客户端发来的请求InputStream inputStream = socket.getInputStream();DataInputStream dataInputStream = new DataInputStream(inputStream);//打印结果String result = dataInputStream.readUTF();System.out.println("服务器端收到了客户端发来的请求 : " + result);dataInputStream.close();inputStream.close();}
}
端口:机器内独一无二的场所

有些时候,一个IP地址并不足以完整标识一个服务器。这是由于在一台物理性的机器中,往往运行着多个服务器(程序)。由IP 表达的每台机器也包含了“端口”(Port)。我们设置一个客户机或者服务器的时候,必须选择一个无论客户机还是服务器都认可连接的端口。就象我们去拜会某人时,IP 地址是他居住的房子,而端口是他在的那个房间。注意端口并不是机器上一个物理上存在的场所,而是一种软件抽象(主要是为了表述的方便)。客户程序知道如何通过机器的IP 地址同它连接,但怎样才能同自己真正需要的那种服务连接呢(一般每个端口都运行着一种服务,一台机器可能提供了多种服务,比如HTTP 和 FTP等等)?端口编号在这里扮演了重要的角色,它是必需的一种二级定址措施。也就是说,我们请求一个特定的端口,便相当于请求与那个端口编号关联的服务。“报时”便是服务的一个典型例子。通常,每个服务都同一台特定服务器机器上的一个独一无二的端口编号关联在一起。客户程序必须事先知道自己要求的那项服务的运行端口号。系统服务保留了使用端口1 到端口 1024 的权力,所以不应让自己设计的服务占用这些以及其他任何已知正在使用的端口。

服务器的全部工作就是等候建立一个连接,然后用那个连接产生的Socket创建一个 InputStream 以及一个OutputStream。在这之后,它从InputStream读入的所有东西都会反馈给OutputStream,直到接收到行中止(END)为止,最后关闭连接。客户机连接与服务器的连接,然后创建一个OutputStream。文本行通过 OutputStream发送。客户机也会创建一个InputStream,用它收听服务器说些什么(本例只不过是反馈回来的同样的字句)。服务器与客户机(程序)都使用同样的端口号,而且客户机利用本地主机地址连接位于同一台机器中的服务器(程序),所以不必在一个物理性的网络里完成测试(在某些配置环境中,可能需要同真正的网络建立连接,否则程序不能工作——尽管实际并不通过那个网络通信)

ServerSocket需要的只是一个端口编号,不需要 IP地址(因为它就在这台机器上运行)。调用accept()时,方法会暂时陷入停顿状态(堵塞),直到某个客户尝试同它建立连接。换言之,尽管它在那里等候连接,但其他进程仍能正常运行(参考第 14章)。建好一个连接以后,accept()就会返回一个 Socket 对象,它是那个连接的代表。清除套接字的责任在这里得到了很艺术的处理。假如ServerSocket 构建器失败,则程序简单地退出(注意必须保证ServerSocket 的构建器在失败之后不会留下任何打开的网络套接字)。针对这种情况,main()会“掷”出一个IOException 违例,所以不必使用一个try块。若 ServerSocket构建器成功执行,则其他所有方法调用都必须到一个 try-finally代码块里寻求保护,以确保无论块以什么方式留下,ServerSocket都能正确地关闭。

网路登录,双向通信

用户实体类, get set省略
public class Person implements Serializable {//账号private String son;//密码private String password;
}
客户端
public class ClientTest {public static void main(String[] args) throws IOException {//localhost 表示 127.0.0.1 也就是主机自身  8080表示端口号  一般的web项目默认端口号是8080Socket socket = new Socket(InetAddress.getByName("localhost"),8080);//向服务器端发出一个请求InputStream inputStream = socket.getInputStream();OutputStream outputStream = socket.getOutputStream();//使用对象流ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);//获得用户输入的结果Person person = new Person("369613719","123456");//将对象发送过去objectOutputStream.writeObject(person);//接受服务器发来的结果DataInputStream dataInputStream = new DataInputStream(inputStream);System.out.println(dataInputStream.readUTF());//释放资源outputStream.close();objectOutputStream.close();}
}
服务器端
public class ServerTest {public static void main(String[] args) throws IOException, ClassNotFoundException {System.out.println("----------------服务器已启动----------------");//监听客户端ServerSocket serverSocket = new ServerSocket(8080);Socket socket = serverSocket.accept();//创建流用来数据传输OutputStream outputStream = socket.getOutputStream();InputStream inputStream = socket.getInputStream();ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);DataOutputStream dataOutputStream = new DataOutputStream(outputStream);//接受客户端发来的请求Person person = (Person) objectInputStream.readObject();String result = "";//判断是否登陆成功if("369613719".equals(person.getSon()) && "123456".equals(person.getPassword())){result = "登陆成功";}else{result = "登录失败";}//发送结果dataOutputStream.writeUTF(result);//释放资源inputStream.close();outputStream.close();objectInputStream.close();dataOutputStream.close();}
}

使用ObjectInputStream与ObjectOutputStream来实现对象的传递时需要注意的是。如果client端的源程序与server端的源程序位于两个项目中,那么需要传递对象的类的包名必须一样,否则会抛出:java.lang.ClassNotFoundException的异常。

Web全栈~28.网络编程相关推荐

  1. 全栈必备 网络编程基础

    我们是幸运的,因为我们拥有网络.网络是一个神奇的东西,它改变了你和我的生活方式,改变了整个世界. 然而,网络的无标度和小世界特性使得它又是复杂的,无所不在,无所不能,以致于我们无法区分甚至无法描述. ...

  2. 开课吧mysql课件百度云_开课吧web全栈十二期|百度云|天翼云下载

    目录:/Web全栈架构师第12期 [93.1G] ┣━━阶段10:webpack [6.2G] ┃ ┣━━10-1 01课 webpack实战 (2019.11.21).mp4 [1.7G] ┃ ┣━ ...

  3. php web教程视频教程下载,Web全栈 PHP+React系列视频教程下载

    Web全栈 PHP+React系列视频教程下载 课程介绍: 此套Web全栈 PHP+React系列视频教程覆盖PHP.前端和区块链应用开发三大热门职位,教程对网络基础.前端基础(HTML CSSJav ...

  4. 用好CloudIDE提升Web全栈编码效率

    学了Web全栈开发,就得动手实践,要动手,得先有开发环境. 比如要开发python代码,是先在自己机器上安装python3,然后安装pycharm社区版 其实这些事情,说难不难,说容易也不容易 说难, ...

  5. Bootstrap实战练习---Web全栈课程体系(表格+巨幕)

    Bootstrap实战练习-Web全栈课程体系(表格+巨幕) 原网页效果图 连接 我的网页效果 -我的代码 <!DOCTYPE html> <html> <head> ...

  6. Web全栈~25.文件

    Web全栈~25.文件 上一期 前言 Web全栈系列博客到了文件这里已经逐步的走向重点.前面的内容之所以很多都不全面,其实根本原因还是自己太懒...当然对于一些细节日后会在其他系列的博客去说 事实上我 ...

  7. Web全栈~26.IO

    Web全栈~26.IO 上一期 Java处理文件的常见方法 IO流 在Java中,文件是视为输入输出(Input/Output , IO)设备的一种.Java使用基本统一的概念来处理所有的IO,包括键 ...

  8. 苏州木渎计算机课程培训,苏州木渎H5/web全栈开发培训

    课程名称:H5/web全栈开发 课程类型:网页设计 班型:全日制/周末班/晚班 适用校区:全校区 课程详情: 由于网络的发展以及人们使用网络的频繁性,企业需要通过网页呈现产品.服务.理念.文化,或向大 ...

  9. 【融职教育】Web全栈工程师课程安排

    课程安排说明 Web全栈就业班分为五个阶段,共计120个学习日,前四个阶段共计100个学习日,最后一个阶段安排入职企业实习.Web全栈开发就业班学习的技术非常的全面,内容很多,为了能更好的了解课程内容 ...

最新文章

  1. h5新增浏览器本地缓存localStorage
  2. 80端口被system(pid=4)占用的解决方法
  3. fastjson Features 说明
  4. 真实临在--摘自{《信仰在我家》}
  5. mybatis Table book.t_abmin not find
  6. Hadoop HDFS原理
  7. 中标2020中国联通数据设备集采项目,中兴通讯备受鼓舞
  8. LoadRunner教程(12)-LoadRunner IP欺骗
  9. 计算机培训日志范文30篇,班主任工作日志20篇.docx
  10. Vulkan简介(1)
  11. (十九)VMware Harbor 详细介绍
  12. 多维联合正态分布代码matlab(以二维为例)
  13. correl函数相关系数大小意义_相关系数越大,说明两个变量之间的关系就越强吗...
  14. win7 正在锁定计算机 卡住,win7关机关不掉怎么办_win7一直卡在关机的解决办法
  15. 一生总会遇到那么一个人
  16. proteus学习教程大全
  17. 低功耗蓝牙设备DA1458x芯片开发之更新连接参数
  18. 前端工程化: 脚手架+物料库快速生成新项目
  19. 计算机二级vb重点知识,计算机二级《VB》常考知识点归纳
  20. Python_从零开始学习_(52) 飞机大战_发射子弹

热门文章

  1. k8s event 事件输入elk 并设置钉钉报警
  2. IR的评价指标-MAP,NDCG和MRR
  3. PHP:【微信小程序】初识微信小程序,微信小程序配置
  4. nginx配置和优化详解
  5. 宿主机与开发板网络共享
  6. 【问题描述】编写一个程序计算出球、圆柱和圆锥的表面积和体积。
  7. jstack命令 详解
  8. Excel:多个单元格内容合并——“”-PHONETIC()函数-Text()函数
  9. [Linux]进程概念以及进程状态
  10. FreeRTOS-时间片与任务阻塞的实现