< 笔记 > Java SE
来源:互联网 发布:学乐器的软件 编辑:程序博客网 时间:2024/05/29 07:10
08 Java SE 网络编程
By Kevin Song
- 08-01 网络模型概述
- 08-02 TCP和UDP协议
- 08-03 网络编程其他
08-01 网络模型概述
网络模型
OSI(Open System Interconnection)开放系统互联参考模型
- 应用层
- 终端应用
- 表示层
- 把计算机能识别的东西表示成人能识别的东西
- 会话层
- 在系统之间发起会话,会话请求
- 传输层
- 定义传输协议和端口号
- TCP(传输控制协议)
- 传输效率低
- 可靠性强
- 传输数据量大的数据
- UDP(用户数据报协议)
- 可靠性低
- 传输数据量小的数据
- TCP(传输控制协议)
- 这一层数据叫:段
- 定义传输协议和端口号
- 网络层
- IP地址的封装和解封装
- 这一层数据叫:数据包
- 这一层设备是:路由器
- 数据链路层
- MAC地址的封装和解封装
- 这一层数据叫:帧
- 这一层设备是:交换机
- 物理层
- 定义物理设备标准
- 作用是传输比特流
- 这一层数据叫:比特
- 应用层
TCP/IP参考模型
- 应用层:数据段
- 传输层:数据包
- 网际互连层:数据帧
- 网络接入层:比特
网络通讯要素
- IP地址
- 网络中设备的标识
- 本地回环地址:127.0.0.1 主机名:localhost
- 端口号
- 用于标识进程的逻辑地址
- 有效端口:0 - 65535
- 系统保留端口:0 - 1024
- 传输协议
- 通讯的规则
- 常见协议
- TCP(传输控制协议)
- 建立链接,形成传输数据的通道
- 在连接中进行大数据量传输
- 通过三次握手完成连接,所以可靠
- Client:Server 帮个忙噻
- Server:干什么噻
- Client:那就谢谢了
- 因为要连接,所以速度慢
- 类似电话
- UDP(用户数据报协议)
- 数据和源目封装成数据包,不需要建立连接
- 每个数据报文限制在64k内
- 因为无连接,所以不可靠
- 因为无连接,所以速速快
- 类似对讲机
- TCP(传输控制协议)
InetAddress类
作用:InetAddress类表示互联网协议(IP)地址
public class IPDemo { public static void main(String[] args) { //获取本地主机ip地址对象 InetAddress ip = InetAddress.getLocalHost(); //获取其他主机ip地址对象 ip = InetAddress.getByName("192.168.1.100"); System.out.println(ip.getHostAddress()); System.out.println(ip.getHostName()); }}
08-02 TCP和UDP协议
Socket
- Socket就是为网络服务提供的一种机制
- 通信的两段都有Socket
- 网络通信其实就是Socket间的通信
- 数据在两个Socket间通过IO传输
UDP协议
UDP协议发送端
创建UDP发送端思路
- 建立UDP的socket服务
- 将要发送的数据封装到数据包中
- 通过UDP的socket服务将数据包发送出去
- 关闭socket服务
public class UDPSendDemo { public static void main(String[] args) { //1.建立UDP的socket服务 DatagramSocket ds = new DatagramSocket(); //2.将要发送的数据封装到数据包中 String str = "UDP transmitting"; //用DatagramPacket将数据封装到该对象中 byte[] buf = str.getBytes(); DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.0.100"),10000); //3.通过UDP的Socket服务将数据包发送出去 ds.send(dp); //4.关闭socket服务 ds.close(); }}
UDP协议接收端
创建UDP接收端思路:
- 建立UDP的socket服务,必须明确端口号
- 将要接受的数据存储到数据包中
- 用socket的receive方法接收数据,存储到数据包中
- 通过数据包的方法解析数据包中的数据
- 关闭socket服务
public class UDPReceiveDemo { public static void main(String[] args) { //1.建立UDP的socket服务 DatagramSocket ds = new DatagramSocket(10000); //2.创建数据包 byte[] buf = new byte[1024]; DatagramPacket dp = new DatagramPacket(buf, buf.length); //3.使用接收方法将数据存储到数据包中 ds.receive(dp); //4.通过数据包方法解析数据 String ip = dp.getAddress().getHostAddress(); int port = dp.getPort(); String text = new String(dp.getData(),0,dp.getLength()); System.out.println(ip+":"+port+":"+text); //5.关闭资源 ds.close();}
聊天程序
public class UDPSendDemo { public static void main(String[] args) { //1.建立UDP的socket服务 DatagramSocket ds = new DatagramSocket(8888); //2.将要发送的数据封装到数据包中 //String str = "UDP transmitting"; BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in)); String line = null; while((line=bufr.readLine())!=null) { if("over".equals(line)) break; byte[] buf = line.getBytes(); //用DatagramPacket将数据封装到该对象中 DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.0.100"),10000); //3.通过UDP的Socket服务将数据包发送出去 ds.send(dp); } //4.关闭socket服务 ds.close(); }}
public class UDPReceiveDemo { public static void main(String[] args) { //1.建立UDP的socket服务 DatagramSocket ds = new DatagramSocket(10000); while(true) { //持续接收数据 byte[] buf = new byte[1024]; DatagramPacket dp = new DatagramPacket(buf, buf.length); //3.使用接收方法将数据存储到数据包中 ds.receive(dp); //4.通过数据包方法解析数据 String ip = dp.getAddress().getHostAddress(); int port = dp.getPort(); String text = new String(dp.getData(),0,dp.getLength()); System.out.println(ip+":"+port+":"+text); } //2.创建数据包 //5.关闭资源 //ds.close();}
多线程实现的聊天程序
public class ChatDemo { /** * @param args * @throws IOException */ public static void main(String[] args) throws IOException { DatagramSocket send = new DatagramSocket(); DatagramSocket rece = new DatagramSocket(10001); new Thread(new Send(send)).start(); new Thread(new Rece(rece)).start(); }}public class Rece implements Runnable { private DatagramSocket ds; public Rece(DatagramSocket ds) { this.ds = ds; } @Override public void run() { try { while (true) { byte[] buf = new byte[1024]; DatagramPacket dp = new DatagramPacket(buf, buf.length); ds.receive(dp); String ip = dp.getAddress().getHostAddress(); int port = dp.getPort(); String text = new String(dp.getData(), 0, dp.getLength()); System.out.println(ip + "::" + text); if(text.equals("886")){ System.out.println(ip+""); } } } catch (Exception e) { } }}public class Send implements Runnable { private DatagramSocket ds; public Send(DatagramSocket ds){ this.ds = ds; } @Override public void run() { try { BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in)); String line = null; while((line=bufr.readLine())!=null){ byte[] buf = line.getBytes(); DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.255"),10001); ds.send(dp); if("886".equals(line)) break; } ds.close(); } catch (Exception e) {} }}
TCP协议
概述
- Socket和ServerSocket
- 建立客户端和服务端
- 建立连接后,通过Socket中的IO流进行数据的传输
- 关闭Socket
客户端
建立客户端思路
- 创建TCP客户端Socket服务
- 使用Socket对象
- 建议该对象已创建就明确目的地,要连接的主机
- 如果连接建立成功,说明数据传输通道已建立
- 通道就是Socket流,包含输入输出
- 通过Socket来获取输入输出对象
- 通过getOutputStream()和getInputStream()来获取输入输出字节流
- 使用输出流,发送到服务器
- 关闭资源
public class ClientDemo { public static void main(String[] args) { //1.创建客户端socket服务 Socket socket = new Socket("192.168.1.100", 10002); //2.获取socket流中的输出流 OutputStream out = socket.getOutputStream(); //3.使用输出流将制定的数据写出去 out.write("TCP transmitting".getBytes()); //4.关闭资源 socket.close(); }}
服务端
建立服务端思路
- 创建TCP服务端Socket服务
- 使用ServerSocket对象
- 服务端必须对外提供一个端口,否则客户端无法连接
- 获取连接过来的客户端对象
- 通过客户端对象获取socket流读取客户端发来的数据
- 关闭资源(客户端,服务端资源都要关闭)
public class ServerDemo { public static void main(String[] args) { //1.创建服务端socket服务 ServerSocket ss = new ServerSocket(10002); //2.获取连接过来的客户端对象 Socket s = ss.accept(); String ip = s.getInetAddress().getHoustAddress(); //3.通过Socket对象读取输入流,读取客户端发来的数据 InputStream in = s.getInputStream(); byte[] buf = new byte[1024]; int len = in.read(buf); String text = new String(buf,0,len); System.out.println("server:"+text); //4.关闭客户端,关闭服务端 s.close(); ss.close(); }}
客户端服务端交互
public class ClientDemo { public static void main(String[] args) { //1.创建客户端socket服务 Socket socket = new Socket("192.168.1.100", 10002); //2.获取socket流中的输出流 OutputStream out = socket.getOutputStream(); //3.使用输出流将制定的数据写出去 out.write("TCP transmitting".getBytes()); //读取服务端返回的数据,使用socket读取流 InputStream in = socket.getInputsStream(); byte[] buf = new byte[1024]; int len = in.read(buf); String text = new String(buf,0,len); System.out.println(text); //4.关闭资源 socket.close(); }}
public class ServerDemo { public static void main(String[] args) { //1.创建服务端socket服务 ServerSocket ss = new ServerSocket(10002); //2.获取连接过来的客户端对象 Socket s = ss.accept(); String ip = s.getInetAddress().getHoustAddress(); //3.通过Socket对象读取输入流,读取客户端发来的数据 InputStream in = s.getInputStream(); byte[] buf = new byte[1024]; int len = in.read(buf); String text = new String(buf,0,len); System.out.println(ip+":"+text); //使用客户端Socket对象的输出流给客户端返回数据 OutputStream out = s.getOutpuStream(); out.write("Roger that".getBytes()); //4.关闭客户端,关闭服务端 s.close(); ss.close(); }}
文本转换
客户端思路
- 创建socket客户端对象
- 获取键盘录入
- 将录入的信息发送给socket输出流
public class TransClient { public static void main(String[] args) { //1.创建socket客户端对象 Socket s = new Socket("192.168.1.100",10004); //2.获取键盘输入 BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in)); //3.socket输出流 //new BufferedWriter(new OutputStreamWriter(s.getOutputStream)); PrintWriter out = new PrintWriter(s.getOutputStream(),true); //4.socket输入流,读取服务端返回的大写数据 BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream())); String line = null; while((line=bufr.readLine())!=null) { if("over".equals(line)) break; out.println(line); //读取服务器发回的一行大写数据 String upperStr = bufIn.readLine(); System.out.println(upperStr); } s.close(); }}
服务端思路
- ServerSocket服务
- 获取Socket对象
- 源:socket,读取客户端发过来的需要转换的数据
- 目的:显示在控制台上
- 转换成大写发送给客户端
public class TransServer { public static void main(String[] args) { //1.ServerSocket服务 ServerSocket ss = new ServerSocket(10004); //2.获取socket对象 Socket s = ss.accept(); //获取IP String ip = s.getInetAddress().getHostAddress(); System.out.println(ip+"......connected"); //3.获取socket读取流并装饰 BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream())); //4.获取socket输出流并装饰 PrintWriter out = new PrintWriter(s.getOutputStream(),true); String line = null; while((line=bufIn.readLine())!=null){ System.out.println(line); out.println(line.toUpperCase()); //out.print(line.toUpperCase()+"\r\n"); //out.flush(); } s.close(); ss.close();}
上传文本文件
public class UploadClient { public static void main(String[] args) { Socket s = new Socket("192.168.1.100",10005); BufferedReader bufr = new BufferedReader(new FileReader("client.txt")); PrintWriter out = new PrintWriter(s.getOutputStream(),true); String line = null; while((line=bufr.readLine())!=null) { out.println(line); } //告诉服务端,客户端写完了 s.shutdownOutput(); //out.println("over"); BufferedRedaer bufIn = new BufferedReader(new InputStreamReader(s.getInputStream())); String str = bufIn.readLine(); System.out.println(str); bufr.close(); s.close(); }}
public class UploadServer { public static void main(String[] args) { ServerSocket ss = new ServerSocket(10005); Socket s = ss.accept(); System.out.println(s.getInetAddress().getHostAddress()+"...connected"); BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream())); BufferedWriter bufw = new BufferedWriter(new FileWriter("server.txt")); String line = null; while((line=bufIn.readLine())!=null) { if("over".equals(line)) break bufw.write(line); bufw.newLine(); bufw.flush(); } PrintWriter out = new PrintWriter(s.getOutputStream(),true); out.println("upload complete"); bufw.close(); s.close(); ss.close(); }}
上传图片
public class UploadPicClient { public static void main(String[] args) throws UnknownHostException, IOException { //1,创建客户端socket。 Socket s = new Socket("192.168.1.100",10006); //2,读取客户端要上传的图片文件。 FileInputStream fis = new FileInputStream("c:\\0.bmp"); //3,获取socket输出流,将读到图片数据发送给服务端。 OutputStream out = s.getOutputStream(); byte[] buf = new byte[1024]; int len = 0; while((len=fis.read(buf))!=-1){ out.write(buf,0,len); } //告诉服务端说:这边的数据发送完毕。让服务端停止读取。 s.shutdownOutput(); //读取服务端发回的内容。 InputStream in = s.getInputStream(); byte[] bufIn = new byte[1024]; int lenIn = in.read(buf); String text = new String(buf,0,lenIn); System.out.println(text); fis.close(); s.close(); }}
public class UploadPicServer { public static void main(String[] args) throws IOException { //创建tcp的socket服务端。 ServerSocket ss = new ServerSocket(10006); //获取客户端 while(true) { Socket s = ss.accept(); new Thread(new UploadTask(s)).start(); } //ss.close(); }}public class UploadTask implements Runnable { private Socket s; private UploadTask(Socket s) { this.s = s;} @Override public void run() { int count = 0; String ip = s.getInetAddress().getHostAddress(); System.out.println(ip+"...connected"); //读取客户端发来的数据 try { InputStream in = s.getInputStream(); //将读取到数据存储到一个文件中 File dir = new File("c:\\pic"); if(!dir.exists()) { dir.mkdirs(); } File file = new File(dir,ip+".jpg"); if(file.exists()) { file = new File(dir,ip+"("+(++count)+").jpg"); } FileOutputStream fos = new FileOutputStream(file); byte[] buf = new byte[1024]; int len = 0; while((len=in.read(buf)!=-1)) { fos.write(buf,0,len); } //获取socket输出流,把文件发送给客户端 OutputStream out = s.getOutputStream(); out.wirte("upload complete".getBytes()); fos.close(); s.close(); } catch (IOException e) {} }}
08-03 网络编程其他
常见客户端和服务端
常见的客户端
- 浏览器
- Chrome,Edge,Firefox
常见的服务端
- 服务器
- Tomcat
自定义客户端和服务端
自定义服务端
- 自定义服务端,使用已有的客户端IE,了解客户端给服务器端发了什么请求
public class MyTomcat { public static void main(String[] args) throws IOException { ServerSocket ss = new ServerSocket(9090); Socket s = ss.accept(); System.out.println(s.getInetAddress().getHostAddress()+".....connected"); InputStream in = s.getInputStream(); byte[] buf = new byte[1024]; int len = in.read(buf); String text = new String(buf,0,len); System.out.println(text); //给客户端一个反馈信息。 PrintWriter out = new PrintWriter(s.getOutputStream(),true); out.println("<font color='red' size='7'>欢迎光临</font>"); s.close(); ss.close(); }}
服务端获取的信息如下:
请求行 请求方式
GET / HTTP/1.1 /myweb/1.html 请求的资源路径 http协议版本
请求消息头,属性名:属性值
**Accept: */*
Accept-Language: zh-cn, zu;q=0.5
Accept-Encoding:gzip, deflate
User-Agent: Mozilla/4.0
Host: 192.168.1.105:9090
Connection: Keep-Alive**
//空行(请求头和请求体之间有空行)
请求体
……
自定义客户端
public class MyBrowser { public static void main(String[] args) throws UnknownHostException, IOException { Socket s = new Socket("192.168.1.100",8080); //模拟浏览器,给tomcat服务端发送符合http协议的请求消息。 PrintWriter out = new PrintWriter(s.getOutputStream(),true); out.println("GET /myweb/1.html HTTP/1.1"); out.println("Accept: */*"); out.println("Host: 192.168.1.100:8080"); out.println("Connection: close"); out.println(); out.println(); InputStream in = s.getInputStream(); byte[] buf = new byte[1024]; int len = in.read(buf); String str =new String(buf,0,len); System.out.println(str); s.close(); //http://192.168.1.100:8080/myweb/1.html }}
浏览器获取的信息如下:
HTTP/1.1 200 OK //应答行:http的协议版本 应答状态码 应答状态描述信息
应答消息头 属性名:属性值
**Server: Apache-Coyote/1.1
Etag: W/”199-1323480176984”
Last-Modified: Sat, 10 Dec 2011 01:22:56 GMT
Content-Type:text/html
Content-Length: 100
Date: Fri, 11 May 2012 07:51:39 GMT
Connection: close**
//空行
应答体
<html> <head> <title></title> </head> <body> <h1>欢迎光临</h1> <font size="5" color="red"> html网页 </font> </body></html>
URL&URL Connection
public class URLDemo { public static void main(String[] args) throws MalformedURLException { String str_url = "http://192.168.1.100:8080/myweb/1.html?name=lisi"; URL url = new URL(str_url); /* System.out.println(""+url.getProtocol()); System.out.println(""+url.getHost()); System.out.println(""+url.getPort()); System.out.println(""+url.getFile()); System.out.println(""+url.getPath()); System.out.println(""+url.getQuery()); */ //InputStream in = url.openStream(); //获取url对象的url连接器对象,将连接封装成了对象 //Java中内置的可以解析的具体协议的对象+socket URLConnection conn = url.openConnection(); //System.out.println(conn); InputStream in = conn.getInputStream(); byte[] buf = new byte[1024]; int len = in.read(buf); String text = new String(buf,0,len); System.out.println(text); in.close(); }}
常见网络架构
- C/S (Client/Server)
- 缺点
- 客户端服务端都需要开发
- 开发成本高,维护麻烦
- 优点
- 客户端在本地可以分担运算
- 缺点
- B/S (Browser/Server)
- 优点
- 服务端需要开发,客户端不需要开发,直接用浏览器
- 开发成本相对C/S低,维护简单
- 缺点
- 所有运算都在服务端完成
- 优点
- JAVA SE学习笔记
- Java se笔记_2
- JAVA SE 笔记
- Java SE 详细笔记
- JAVA SE 学习笔记
- java se 集合 笔记
- java se 学习笔记
- < 笔记 > Java SE
- < 笔记 > Java SE
- < 笔记 > Java SE
- < 笔记 > Java SE
- < 笔记 > Java SE
- < 笔记 > Java SE
- < 笔记 > Java SE
- < 笔记 > Java SE
- < 笔记 > Java SE
- < 笔记 > Java SE
- Java SE 自学笔记1
- poj2586 Y2K Accounting Bug
- 关于Access denied for user 'root'@'localhost' (using password:NO)
- 红黑树
- poj 2942 Knights of the Round Table 点-双连通分量 图论综合题
- flume介绍
- < 笔记 > Java SE
- 网站被封申诉通道方式方法
- 《数据聚类》书籍序言阅读摘抄及思考——关于人工智能未来研究
- css布局:table布局、两栏布局、三栏布局
- c++ vector
- Socket网络编程基础
- Android事件分发机制(View)
- synchronized关键字
- vs编译器使用时的问题及解决方案