1 通信协议

通信的协议还是比较复杂的, java.net 包中包含的类和接口,它们提供低层次的通信细节。我们可以直接使用这些类和接口,来专注于网络程序开发,而不用考虑通信的细节。
java.net 包中提供了两种常见的网络协议的支持:tcp和udp

TCP:传输控制协议 (Transmission Control Protocol)。TCP协议是面向连接的通信协议,即传输数据之前,在发送端和接收端建立逻辑连接,然后再传输数据,它提供了两台计算机之间可靠无差错的数据传输。

三次握手:TCP协议中,在发送数据的准备阶段,客户端与服务器之间的三次交互,以保证连接的可靠。
第一次握手,客户端向服务器端发出连接请求,等待服务器确认。
第二次握手,服务器端向客户端回送一个响应,通知客户端收到了连接请求。
第三次握手,客户端再次向服务器端发送确认信息,确认连接。整个交互过程如下图所示。

UDP:用户数据报协议(User Datagram Protocol)。UDP协议是一个面向无连接的协议。传输数据时,不需要建立连接,不管对方端服务是否启动,直接将数据、数据源和目的地都封装在数据包中,直接发送。每个数据包的大小限制在64k以内。它是不可靠协议,因为无连接,所以传输速度快,但是容易丢失数据。日常应用中,例如视频会议、QQ聊天等。耗资小效率高,容易丢数据

2 网络编程三要素

协议:计算机网络通信必须遵守的规则。

IP地址:指互联网协议地址(Internet Protocol Address),俗称IP。IP地址用来给一个网络中的计算机设备做唯一的编号。假如我们把“个人电脑”比作“一台电话”的话,那么“IP地址”就相当于“电话号码”。

IP地址分类

  • IPv4:是一个32位的二进制数,通常被分为4个字节,表示成a.b.c.d 的形式,例如192.168.65.100 。其中a、b、c、d都是0~255之间的十进制整数,那么最多可以表示42亿个。
  • IPv6:由于互联网的蓬勃发展,IP地址的需求量愈来愈大,但是网络地址资源有限,使得IP的分配越发紧张。有资料显示,全球IPv4地址在2011年2月分配完毕。为了扩大地址空间,拟通过IPv6重新定义地址空间,采用128位地址长度,每16个字节一组,分成8组十六进制数,表示成ABCD:EF01:2345:6789:ABCD:EF01:2345:6789 ,号称可以为全世界的每一粒沙子编上一个网址,这样就解决了网络地址资源数量不够的问题。

常用命令
查看本机IP地址,在控制台输入:ipconfig
检查网络是否连通,在控制台输入:ping ip地址
特殊的IP地址:本机IP地址: 127.0.0.1 、localhost 。

端口号
网络的通信,本质上是两个进程(应用程序)的通信。每台计算机都有很多的进程,那么在网络通信时,如何区分这些进程呢?如果说IP地址可以唯一标识网络中的设备,那么端口号就可以唯一标识设备中的进程(应用程序)了。

端口号:用两个字节表示的整数,它的取值范围是0~65535。其中,0~1023之间的端口号用于一些知名的网络服务和应用,普通的应用程序需要使用1024以上的端口号。如果端口号被另外一个服务或应用所占用,会导致当前程序启动失败。

利用协议+ IP地址+ 端口号 三元组合,就可以标识网络中的进程了,那么进程间的通信就可以利用这个标识与其它进程进行交互。

常用端口号

  • 80端口 网络端口
  • 数据库端口 mysql:3306 oracle:1521
  • tomcat端口:8080

3 TCP通信程序

TCP通信能实现两台计算机之间的数据交互,通信的两端要严格区分客户端和服务端

通信步骤

  1. 服务器端先启动
  2. 客户端请求服务器端
  3. 客户端服务端经过三次握手建立逻辑连接
  4. 连接中包含一个IO对象,使用IO流对象进行通信,IO流对象是字节流对象。

服务端要做的事

  1. 服务端需要知道自己在和哪个客户端交互,通过accept方法获取到请求的客户端对象
  2. 多个客户端和服务端交互需要使用多个IO流对象。服务端没有IO流,它可以获取到请求的客户端对象socket使用每个客户端的socket中提供的IO流和客户端进行交互。使用输入流读数据,使用输出流发数据。

3.1 TCP客户端代码实现

构造方法:Socket(String host, int port)

成员方法

  • OutputStream getOutputStream():返回输出流
  • InputStream getInputStream():返回输入流
  • void close():关闭套接字

实现步骤

  1. 创建客户端对象Socket,绑定服务器IP地址和端口号
  2. 使用socket对象的getOutputStream()获取网络字节输出流对象
  3. 使用字节输出流的write方法发送数据
  4. 使用socket对象的getInputStream()获取网络字节输入流对象
  5. 使用字节输入流的read方法读取数据
  6. 释放资源
public class TCPClient {public static void main(String[] args) throws IOException {Socket socket = new Socket("127.0.0.1",8888);OutputStream os = socket.getOutputStream();os.write("客户端:你好服务器".getBytes());InputStream is = socket.getInputStream();byte[] bytes = new byte[1024];int len = is.read(bytes);System.out.println(new String(bytes,0,len));socket.close();}
}

3.2 TCP服务端代码实现

构造方法:Socket(int port):创建绑定到特定端口的服务器套接字

成员方法

  • Socket accept():侦听并接收到此套接字连接
    实现步骤
  1. 创建客户端对象Socket,绑定服务器IP地址和端口号
  2. 使用socket对象的getOutputStream()获取网络字节输出流对象
  3. 使用字节输出流的write方法发送数据
  4. 使用socket对象的getInputStream()获取网络字节输入流对象
  5. 使用字节输入流的read方法读取数据
  6. 释放资源
public class TCPServer {public static void main(String[] args) throws IOException {ServerSocket server = new ServerSocket(8888);Socket socket = server.accept();InputStream is = socket.getInputStream();byte[] bytes= new byte[1024];int len = is.read(bytes);System.out.println(new String(bytes, 0, len));OutputStream os = socket.getOutputStream();os.write("服务端:收到谢谢".getBytes());socket.close();server.close();}
}

3.3 练习1-文件上传

原理:客户端读取本地的文件,把文件上传到服务器,服务器把上传的文件保存到服务器的硬盘上。

步骤

  1. 客户端使用本地的字节输入流,读取要上传的文件
  2. 客户端使用网络字节输出流,把读取到的文件上传到服务器
  3. 服务器使用网络字节输入流,读取客户端上传的文件
  4. 服务端使用本地的字节输出流,把读取到的文件保存到服务器的硬盘上
  5. 服务器使用网络字节输出流,给客户端回写一个上传成功
  6. 客户端使用网络字节输入流,读取客户端回写的消息

本地硬盘读写用本地字节流,CS间通信用网络字节流

客户端实现

  1. 创建本地fis对象读取本地文件
  2. 创建socket对象获取网络os对象
  3. 使用网络os对象上传文件到服务器
  4. 使用socket对象获取网络is对象
  5. 使用网络is对象读取服务器回写的数据
  6. 释放资源
//数据源:"a.txt"
//目的地服务器"D:\\upload\\"
public class TCPClient {public static void main(String[] args) throws IOException {FileInputStream fis = new FileInputStream("a.txt");Socket socket = new Socket("127.0.0.1",8888);OutputStream os = socket.getOutputStream();int len = 0;byte[] bytes = new byte[1024];while((len = fis.read(bytes)) != -1){os.write(bytes,0,len);}//上传完文件给服务器写一个结束标记socket.shutdownOutput();InputStream is = socket.getInputStream();while ((len = is.read(bytes)) != -1){System.out.println(new String(bytes,0,len));}fis.close();//从本地读取文件 输出到服务器socket.close();}
}

服务端实现

  1. 创建服务器ServerSocket对象,使用accpet方法获取Socket对象
  2. 使用Socket对象的getInputStream获取网络字节输入流对象
  3. 判断上传的文件夹是否存在,不存在则创建
  4. 创建一个本地的字节输出流fos ,绑定输出目的地
  5. 用网络is对象读取客户端上传的文件
  6. 使用本地字节fos把文件写道服务器的硬盘上
  7. 获取网络os对象,使用os对象的write给客户端发送上传成功的消息
  8. 释放资源

注意上传阻塞问题
fis.read 读取本地文件 结束标记是读取到-1
while循环不会读取-1 也不会写给服务器
read读不到-1 进入死循环
解决方法:上传结束后,写一个结束标记。使用socket.shutdown()

public class TCPServer {public static void main(String[] args) throws IOException {ServerSocket server = new ServerSocket(8888);Socket socket = server.accept();InputStream is = socket.getInputStream();File file = new File("E:\\upload");if(!file.exists()){file.mkdir();}FileOutputStream fos = new FileOutputStream(file+"\\a.txt");byte[] bytes= new byte[1024];int len = 0;while((len = is.read(bytes))!= -1){fos.write(bytes,0,len);}OutputStream os = socket.getOutputStream();os.write("服务端:文件上传成功".getBytes());socket.close();server.close();}
}

3.4 练习2-文件上传优化版

  1. 自定义文件命名,防止文件同名覆盖
  2. 让服务器一直处于监听状态,客户端可以多次上传
  3. 使用多线程可以提高文件上传效率,上传一次开启一个线程
package tcp;import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Random;public class TCPServer {public static void main(String[] args) throws IOException {ServerSocket server = new ServerSocket(8888);//优化2:让服务端一直处于监听状态 死循环accept//有一个客户端上传就保存一个文件while(true){Socket socket = server.accept();//优化3:使用多线程提高效率 run中实现文件文件上传 有一个客户端上传就开启一个线程new Thread(new Runnable() {@Overridepublic void run() {try{InputStream is = socket.getInputStream();File file = new File("E:\\upload");if(!file.exists()){file.mkdir();}//优化1:自定义文件名String filename = "zxc"+System.currentTimeMillis()+new Random().nextInt(9999)+".txt";FileOutputStream fos = new FileOutputStream(file+"\\"+filename);byte[] bytes= new byte[1024];int len = 0;while((len = is.read(bytes))!= -1){fos.write(bytes,0,len);}OutputStream os = socket.getOutputStream();os.write("服务端:文件上传成功".getBytes());socket.close();}catch (IOException e){e.printStackTrace();}}}).start();}}
}

3.5 BS服务器实现

使用FileInputStream创建对象的时候遇到了问题,相对路径访问不了,这个问题暂时还不知道怎么解决,所以强行把父路径加上了,访问绝对路径就没问题。

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;/*创建BS版本TCP服务器*/
public class TCPServerThread {public static void main(String[] args) throws IOException {//创建一个服务器ServerSocket,和系统要指定的端口号ServerSocket server = new ServerSocket(8080);/*浏览器解析服务器回写的html页面,页面中如果有图片,那么浏览器就会单独的开启一个线程,读取服务器的图片我们就的让服务器一直处于监听状态,客户端请求一次,服务器就回写一次*/while(true){//使用accept方法获取到请求的客户端对象(浏览器)Socket socket = server.accept();new Thread(new Runnable() {@Overridepublic void run() {try {//使用Socket对象中的方法getInputStream,获取到网络字节输入流InputStream对象InputStream is = socket.getInputStream();//把is网络字节输入流对象,转换为字符缓冲输入流BufferedReader br = new BufferedReader(new InputStreamReader(is));//把客户端请求信息的第一行读取出来 GET /11_Net/web/index.html HTTP/1.1String line = br.readLine();System.out.println(line);//把读取的信息进行切割,只要中间部分 /11_Net/web/index.htmlString[] arr = line.split(" ");//把路径前边的/去掉,进行截取 11_Net/web/index.htmlString htmlpath = arr[1].substring(1);//使用FileInputStream创建对象的时候遇到了问题//相对路径访问不了 不知道怎么解决//所以强行把父路径加上了//访问绝对路径就没问题File file = new File("").getAbsoluteFile();htmlpath = file.getParent() + "\\" + htmlpath;//创建一个本地字节输入流,构造方法中绑定要读取的html路径FileInputStream fis = new FileInputStream(htmlpath);//使用Socket中的方法getOutputStream获取网络字节输出流OutputStream对象OutputStream os = socket.getOutputStream();// 写入HTTP协议响应头,固定写法os.write("HTTP/1.1 200 OK\r\n".getBytes());os.write("Content-Type:text/html\r\n".getBytes());// 必须要写入空行,否则浏览器不解析os.write("\r\n".getBytes());//一读一写复制文件,把服务读取的html文件回写到客户端int len = 0;byte[] bytes = new byte[1024];while((len = fis.read(bytes))!=-1){os.write(bytes,0,len);}//释放资源fis.close();socket.close();}catch (IOException e){e.printStackTrace();}}}).start();}//server.close();}
}

【Java】网络编程相关推荐

  1. java 密钥工厂 desede_20145212 实验五《Java网络编程》

    20145212 实验五<Java网络编程> 一.实验内容1.运行下载的TCP代码,结对进行,一人服务器,一人客户端: 2.利用加解密代码包,编译运行代码,一人加密,一人解密: 3.集成代 ...

  2. Java学习总结:52(Java网络编程)

    Java网络编程 开发第一个网络程序 java.net包提供了网络编程有关的开发工具类,在此包中有一下两个主要的核心操作类. ServerSocket类:是一个封装支持的TCP协议的操作类,主要工作在 ...

  3. Java - 网络编程(NetWork)

    Java - 网络编程(NetWork) 一.java.net包下的 InetAddress 类的使用: > 一个 InetAddress 代表着一个IP地址 > 主要用来查看本机的IP和 ...

  4. 【Java】 Java网络编程总结

     一.网络编程三要素: IP地址:每个设备在网络中的唯一标识. 端口号:每个程序在设备上的唯一标识. 协议:为计算机网络中进行数据交换而建立的规则或约定的集合. UDP: 面向无连接,数据不安全,速度 ...

  5. Java网络编程笔记5

    在Java网络编程笔记4中我们看到了客户端与服务器通信的过程,只是在前面的程序只是单个客户端与服务器通信 的例子. 接下来我们看如何实现多个客户端与服务器通信,对于服务器来说,它要为每个客户端请求的S ...

  6. 实验五 Java网络编程及安全 实验报告 20135232王玥

    北京电子科技学院(BESTI) 实     验    报     告 课程:Java程序与设计         班级:1352 姓名:王玥 学号:20135232 成绩:             指导 ...

  7. NIO详解(一):java网络编程IO总结(BIO、NIO、AIO)

    1.基本概念 在Java网络通信中,最基本的概念就是Socket编程了.Socket又称"套接字" 向网络发出请求或者应答网络请求. Socket 和ServerSocket类库位 ...

  8. 04.Java网络编程(转载)

    1.网络编程 1.1计算机网络概述 网络编程的实质就是两个(或多个)设备(例如计算机)之间的数据传输. 按照计算机网络的定义,通过一定的物理设备将处于不同位置的计算机连接起来组成的网络,这个网络中包含 ...

  9. python网络编程视频教程_Java网络开发视频教程 – 一站式学习Java网络编程视频教程 全面理解BIO(无密)...

    Java网络开发视频教程 – 一站式学习Java网络编程视频教程 全面理解BIO(无密) 全面理解BIO/NIO/AIO 网络层编程,是每一个开发者都要面对的技术.课程为解决大家学习网络层知识的难题, ...

  10. 你所需要的java网络编程大总结

    好好学java java知识分享/学习教程免费分享 关注 精彩内容 你所需要的java全套视频教程 你所需要的java电子图书 你所需要的大数据视频教程 你所需要的java练习项目 如 / 梦 上个月 ...

最新文章

  1. 王高利:awstats
  2. 基于动态用户偏好和服务质量的推荐算法
  3. 计算机网络·数据链路层.三个基本问题
  4. 国内常见的电子地图坐标介绍
  5. 为进大厂刷爆算法题,最后却倒在了基础题上?太苦了!
  6. 【数据结构与算法】之深入解析“二叉树的中序遍历”的求解思路与算法示例
  7. Visio矢量图导出教程
  8. Sql Function defference returns and returns
  9. 使用sprintf连接字符串
  10. Autojs之QQ 群发消息(是QQ 群发,不是QQ群 发)
  11. http://blog.csdn.net/wsj18808050/article/details/62226574
  12. (十四)覆盖率类型、覆盖率组
  13. PHP 规则引擎 Hoa\Ruler
  14. VPS云主机套餐中都包含什么
  15. 麒麟os或将取代android,国产自研操作系统新希望!华为或自研麒麟OS欲取代Android...
  16. 【Unity3D 教程系列第 16 篇】Scene视图很清楚,但是Game视图却很模糊的解决方案
  17. 那些程序员们后知后觉的职涯经验
  18. PHP生成曲线统计图表示例,直方图等数据
  19. 爬虫学习(03): 数据解析_re篇
  20. 艾默生流量计旗下其他产品的特点以及应用概况

热门文章

  1. 你确定不反编译 likely 看看?
  2. webmvcconfigurer配置跨域_为什么加了 Spring Security 会导致 Spring Boot 跨域失效呢?...
  3. 高嘌呤食物搜索引擎_“高嘌呤”的食物已发现,尿酸高的人,要尽量挑着吃!...
  4. 流浪地球开机动画包zip_影视日报|合家欢动画电影quot;许愿神龙quot;定档1.15;流浪地球加长版定档11.26...
  5. 税收分类编码2020_增值税开票系统你会吗?2020最新开票(金税盘版)图文教程详细版...
  6. LeetCode 1893. 检查是否区域内所有整数都被覆盖(差分)
  7. LintCode MySQL 1918. 第二高的球员的身高
  8. LeetCode 第 201 场周赛(304/5614,前5.42%)
  9. LeetCode MySQL 1132. 报告的记录 II
  10. LeetCode 1198. 找出所有行中最小公共元素(二分/合并有序链表)