【JavaSE笔记】网络基础&网络编程

来源:互联网 发布:s7 200编程软件下载 编辑:程序博客网 时间:2024/06/08 06:51
本期知识点:
网络基础
网络编程

一. 网络基础

1.网络模型概述:

计算机网络之间以何种规则进行通信,就是网络模型研究问题。
网络模型一般是指
OSI(Open System Interconnection开放系统互连)七层参考模型
TCP/IP四层参考模型

主机至网络层(物理层 , 数据链路层) , 网际层 , 传输层 , 应用层(应用层 , 表示层 , 会话层)

2.网络模型7层概述:

a. 物理层:

主要定义物理设备标准,如网线的接口类型、光纤的接口类型、各种传输介质的传输速率等。它的主要作用是传输比特流(就是由1、0转化为电流强弱来进行传输,到达目的地后在转化为1、0)。这一层的数据叫做比特。

b. 数据链路层:

主要将从物理层接收的数据进行MAC地址(网卡的地址)的封装与解封装。常把这一层的数据叫做帧。在这一层工作的设备是交换机,数据通过交换机来传输。 

c. 网络层:

主要将从下层接收到的数据进行IP地址(例192.168.0.1)的封装与解封装。在这一层工作的设备是路由器,常把这一层的数据叫做数据包。 

d. 传输层:

定义了一些传输数据的协议和端口号(WWW端口80等),如:TCP(传输控制协议,传输效率低,可靠性强,用于传输可靠性要求高,数据量大的数据),UDP(用户数据报协议,与TCP特性恰恰相反,用于传输可靠性要求不高,数据量小的数据,如QQ聊天数据就是通过这种方式传输的)。主要是将从下层接收的数据进行分段和传输,到达目的地址后再进行重组。常常把这一层数据叫做段。 

e.会话层:

通过传输层(端口号:传输端口与接收端口)建立数据传输的通路。主要在你的系统之间发起会话或者接受会话请求(设备之间需要互相认识可以是IP也可以是MAC或者是主机名) 

f.表示层:

主要是进行对接收的数据进行解释、加密与解密、压缩与解压缩等(也就是把计算机能够识别的东西转换成人能够能识别的东西(如图片、声音等)。 

g.应用层: 

主要是一些终端的应用,比如说FTP(各种文件下载),WEB(IE浏览),QQ之类的(可以把它理解成我们在电脑屏幕上可以看到的东西.就是终端应用)。

3.网络编程的三要素:

ip
端口号
协议

a.IP:

1)IP概述:

所谓IP地址就是给每个连接在Internet上的主机分配的一个32bit地址。 

2)IP的组成:

IP地址 = 网络地址+主机地址
A类IP地址:第一段号码为网络地址,剩下的三段号码为本地计算机的号码
B类IP地址:前二段号码为网络地址,剩下的二段号码为本地计算机的号码
C类IP地址:前三段号码为网络地址,剩下的一段号码为本地计算机的号码

3)IP地址分类:

A类1.0.0.1---127.255.255.254
(1)10.X.X.X是私有地址(私有地址就是在互联网上不使用,而被用在局域网络中的地址)
(2)127.X.X.X是保留地址,用做循环测试用的。

B类128.0.0.1---191.255.255.254

注:172.16.0.0---172.31.255.255是私有地址。

C类192.0.0.1---223.255.255.254

注:192.168.X.X是私有地址

D类224.0.0.1---239.255.255.254
E类240.0.0.1---247.255.255.254

4)特殊地址:

127.0.0.1 回环地址,可用于测试本机的网络是否有问题.ping 127.0.0.1  
DOS命令 ipconfig:查看本机IP地址
xxx.xxx.xxx.255 广播地址

b.端口号:

物理端口:

物理设备对应的端口, 网卡口

逻辑端口:

用来标示我们的计算机上的进程(正在运行的程序) , 端口号的有效范围应该是0-65535,其中0-1024被系统占用或者保留

c.协议(UDP和TCP的区别):

UDP
把数据打成一个数据包 , 不需要建立连接
数据包的大小有限制不能超过64k
因为无连接,所以属于不可靠协议(可能丢失数据)
因为无连接 ,所以效率高
TCP
需要建立连接,形成连接通道
数据可以使用连接通道直接进行传输,无大小限制
因为有链接,所以属于可靠协议

二. 网络编程

1.InetAddress类

a.概述

public class InetAddress extends Objectimplements Serializable
此类表示互联网协议 (IP) 地址。
此类没有构造方法,但是有静态成员方法。

b.常用的方法

public static InetAddress getByName(String host) throws UnknownHostException
在给定主机名的情况下确定主机的 IP 地址。主机名可以是机器名,也可以是其 IP 地址的文本表示形式。
public String getHostAddress() 返回IP地址字符串
public String getHostName() 返回此IP地址的主机名
import java.io.IOException;
import java.net.InetAddress;
public class ipDemo {
public static void main(String[] args) throws IOException {
InetAddress address = InetAddress.getByName("192.168.100.2");
}
System.out.println(address.getHostName());//YangFan (我的电脑的名字)
}

2.Socket通信原理

a.类 Socket

i.概述

public class Socket extends Object
此类实现客户端套接字(也可以就叫“套接字”)。套接字是台机器间通信的端点。
Socket=IP+端口号

ii.常用方法

public void close()throws IOException 关闭此套接字。 
public InetAddress getInetAddress()返回套接字连接的地址。 
public InputStream getInputStream() throws IOException 返回此套接字的输入流。
public OutputStream getOutputStream() throws IOException 返回此套接字的输出流。 
public void shutdownInput() throws IOException   此套接字的输入流置于“流的末尾”。
发送到套接字的输入流端的任何数据都将被确认然后被静默丢弃。 
public void shutdownOutput() throws IOException   禁用此套接字的输出流。
对于 TCP 套接字,任何以前写入的数据都将被发送,并且后跟 TCP 的正常连接终止序列。 如果在套接字上调用 shutdownOutput() 后写入套接字输出流,则该流将抛出 IOException。

b.Socket原理机制:

通信的两端都有Socket。

网络通信其实就是Socket间的通信。

数据在两个Socket间通过IO传输。

3.UDP协议发送/接收数据

a.类 DatagramSocket

i.概述

public class DatagramSocket extends Object
此类表示用来发送和接收数据报包的套接字。
数据报套接字是包投递服务的发送或接收点。
每个在数据报套接字上发送或接收的包都是单独编址和路由的。
从一台机器发送到另一台机器的多个包可能选择不同的路由,也可能按不同的顺序到达。

ii.构造方法

public DatagramSocket(int port, InetAddress laddr) throws SocketException
创建数据报套接字,将其绑定到指定的本地地址。本地端口必须在 0 到 65535 之间(包括两者)。如果 IP 地址为 0.0.0.0,套接字将被绑定到通配符地址,IP 地址由内核选择。
public DatagramSocket()throws SocketException
构造数据报套接字并将其绑定到本地主机上任何可用的端口。套接字将被绑定到通配符地址,IP 地址由内核来选择。

iii.常用方法

public void send(DatagramPacket p)throws IOException
从此套接字发送数据报包。
DatagramPacket 包含的信息指示:将要发送的数据、其长度、远程主机的 IP 地址和远程主机的端口号。 
public void receive(DatagramPacket p)throws IOException
从此套接字接收数据报包。
当此方法返回时,DatagramPacket 的缓冲区填充了接收的数据。数据报包也包含发送方的 IP 地址和发送方机器上的端口号。
public void close()关闭此数据报套接字。

b.类 DatagramPacket

i.概述

public final class DatagramPacket extends Object
此类表示数据报包。 
数据报包用来实现无连接包投递服务。
每条报文仅根据该包中包含的信息从一台机器路由到另一台机器。
从一台机器发送到另一台机器的多个包可能选择不同的路由,也可能按不同的顺序到达。不对包投递做出保证。

ii.构造方法

public DatagramPacket(byte[] buf,int length,InetAddress address,int port)
构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。
length 参数必须小于等于 buf.length。 

iii.常用方法

public InetAddress getAddress() 返回某台机器的 IP 地址

此数据报将要发往该机器或者是从该机器接收到的。

public byte[] getData() 返回数据缓冲区。
public int getLength() 返回将要发送或接收到的数据的长度。

c.发送数据

i.步骤:
1)创建UDP通讯客户端对象(DatagramSocket)
2)创建数据报包对象
3)发送 数据
4)释放资源

d.接收数据

i.步骤: 
1)创建UDP通讯协议服务器端对象(DatagramSocket) 注意要用有参数构造 指定端口号
2)创建数据报包,作用用来接收数据 
3)接收数据 receive(dp) ;
4)解析数据报包,拿出数据 dp.getData(),dp.getLength() 
5) 释放资源
UDP多次发送消息:
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.SocketException;public class UDPServer {public static void main(String[] args) throws IOException {//创建UDP通讯协议服务器端对象DatagramSocket ds = new DatagramSocket(4444);System.out.println("服务器已经开启,等待连接...");//创建数据报包,接收数据while(true){byte[]a=new byte[1024];int len = a.length;DatagramPacket dp = new DatagramPacket(a, len);//接收数据ds.receive(dp);//解析byte[] b = dp.getData(); int len2 = a.length;System.out.println(new String(b, 0, len2));}}}import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.IOException;import java.io.InputStreamReader;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetAddress;import java.net.UnknownHostException;public class UDPClient {public static void main(String[] args) throws IOException {InetAddress address = InetAddress.getByName("192.168.100.2");//创建UDP客户端对象DatagramSocket ds = new DatagramSocket();BufferedReader br = new BufferedReader(new InputStreamReader(System.in));String msg=null;System.out.println("请输入消息:");while((msg=br.readLine())!=null){System.out.println("请输入消息:");byte[] a = msg.getBytes();int len = a.length;DatagramPacket dp = new DatagramPacket(a,len,address,4444);ds.send(dp);}ds.close();}}
UPD的多线程描述:
import java.io.IOException;import java.net.DatagramSocket;public class ThreadDemo {public static void main(String[] args) throws IOException{DatagramSocket sent = new DatagramSocket();DatagramSocket get = new DatagramSocket(4444);new GetThread(get).start();new SendThread(sent).start();}}import java.net.DatagramPacket;import java.net.DatagramSocket;public class GetThread extends Thread {private DatagramSocket ds;public GetThread(DatagramSocket ds) {this.ds = ds; }@Overridepublic void run() {try {System.out.println("服务器已开启,等待连接...");while(true){byte[] by = new byte[1024];int length = by.length;DatagramPacket dp = new DatagramPacket(by, length);//接收ds.receive(dp);//解析byte[] a = dp.getData();int length2 = dp.getLength();String ip = dp.getAddress().getHostAddress();System.out.println("服务端:"+new String(a, 0, length2));}} catch (Exception e) {e.printStackTrace();}}}import java.io.BufferedReader;import java.io.InputStreamReader;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetAddress;import java.util.Scanner;public class SendThread extends Thread {private DatagramSocket ds;public SendThread(DatagramSocket ds) {this.ds=ds;}@Overridepublic void run() {try {InetAddress ia = InetAddress.getByName("192.168.100.2");BufferedReader bfr = new BufferedReader(new InputStreamReader(System.in));String msg=null;while((msg=bfr.readLine())!=null){byte[] a = msg.getBytes();int length = a.length;DatagramPacket dp = new DatagramPacket(a, length,ia,4444);ds.send(dp);}ds.close();} catch (Exception e) {e.printStackTrace();}}}

4.TCP协议发送/接收数据

a.类 ServerSocket

i.概述

public class ServerSocket extends Object
此类实现服务器套接字。服务器套接字等待请求通过网络传入。
用于TCP通讯协议服务器端对象

ii.构造方法 

public ServerSocket(int port)throws IOException 创建绑定到特定端口的服务器套接字。

iii.常用方法

public Socket accept() throws IOException侦听并接受到此套接字的连接。

此方法在连接传入之前一直阻塞。

public void close() throws IOException   关闭此套接字。
public InetAddress getInetAddress()返回此服务器套接字的本地地址。

b.发送数据

步骤:
1)创建TCP客户端的Socket对象
2)获取输出流,写数据
3)写数据
4)释放资源

c.接收数据

步骤:
1)创建TCP服务器端的ServerSocket对象
2)监听客户端
3)获取输入流对象
4)读取数据
5)释放资源

d.TCP传输容易出现的问题

问题:
客户端连接上服务端,两端都在等待,没有任何数据传输。
分析:
因为read方法或者readLine方法是阻塞式。
解决:

自定义结束标记

使用shutdownInput,shutdownOutput方法。

TCP传输数据

import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.Socket;import java.util.Scanner;public class TCP客户端 {public static void main(String[] args) throws IOException {//类 SocketSocket s = new Socket("192.168.100.2", 4444);//获取输出流OutputStream os = s.getOutputStream();os.write(new Scanner(System.in).nextLine().getBytes());//读取服务端反馈回来的信息InputStream is = s.getInputStream();byte[] a = new byte[1024];int len = is.read(a);System.out.println(new String(a,0,len));s.close();}}import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.ServerSocket;import java.net.Socket;import java.util.Scanner;public class TCP服务端 {public static void main(String[] args) throws IOException {ServerSocket ss = new ServerSocket(4444);//监听客户端System.out.println("服务器已开启,等待连接...");Socket sk = ss.accept();System.out.println("一个客户端已经连接");//读取数据InputStream is = sk.getInputStream();byte[] by = new byte[1024*8];int len = is.read(by);System.out.println(new String(by,0,len));//反馈OutputStream os = sk.getOutputStream();os.write("服务端已收到了".getBytes());}}

TCP传输的包装

import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.net.ServerSocket;import java.net.Socket;public class TCP服务端 {public static void main(String[] args) throws IOException {// 创建服务端ServerSocket 套接字ServerSocket ss = new ServerSocket(4444);// 监听客户端System.out.println("服务器已经开启等待连接...");Socket accept = ss.accept();// 获取管道中的输入输出流InputStream is = accept.getInputStream();// 包装管道中的输入流BufferedReader br = new BufferedReader(new InputStreamReader(is));String msg= null;while((msg=br.readLine())!=null){System.out.println(msg);}}}import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.io.OutputStreamWriter;import java.net.Socket;public class TCP客户端 {public static void main(String[] args) throws IOException {//创建  套接字 对象Socket s = new Socket("192.168.0.40", 4444);//获取通道中的输出流OutputStream os = s.getOutputStream();//获取通道中的输入流InputStream is = s.getInputStream();BufferedReader br = new BufferedReader(new InputStreamReader(System.in));//包装输出流BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));String msg = null;while((msg=br.readLine())!=null){bw.write(msg);bw.newLine();bw.flush();}s.close();}}

TCPC传输读取文件内容

import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.FileReader;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.io.OutputStreamWriter;import java.net.Socket;public class TCP_Client {public static void main(String[] args) throws IOException {//1)创建TCP客户端的Socket对象Socket s = new Socket("192.168.100.2", 3333);//2)获取输出流,写数据OutputStream os = s.getOutputStream();InputStream is = s.getInputStream();BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));BufferedReader br = new BufferedReader(new FileReader("测试.txt"));//3)写数据String msg = null;while((msg=br.readLine())!=null){bw.write(msg);bw.newLine();bw.flush();}s.isOutputShutdown();//4)释放资源s.close();br.close();}}
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.net.ServerSocket;import java.net.Socket;public class TCP_Server {public static void main(String[] args) throws IOException {//1)创建TCP服务器端的ServerSocket对象ServerSocket ss = new ServerSocket(3333);System.out.println("服务器已开启,等待连接...");//2)监听客户端Socket s = ss.accept();System.out.println("一个客户端已经连接");//3)获取输入流对象InputStream is = s.getInputStream();OutputStream os = s.getOutputStream();//4)读取数据BufferedReader br = new BufferedReader(new InputStreamReader(is));String msg=null;while((msg=br.readLine())!=null){System.out.println(msg);}}}


TCP传输文件

import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.Socket;public class TCPClient {public static void main(String[] args) throws IOException {//创建 套接字对象Socket s = new Socket("192.168.0.40",4444);InputStream is = s.getInputStream();OutputStream os = s.getOutputStream();BufferedInputStream bi=new BufferedInputStream(new FileInputStream("C:\\Users\\Administrator\\Desktop\\测试.jpg"));BufferedOutputStream bo = new BufferedOutputStream(os);byte[] a = new byte[1024];int length = 0;while((length=bi.read(a))!=-1){bo.write(a,0,length);bo.flush();}s.shutdownOutput();// 读取反馈byte[] by = new byte[1024];int len = is.read(by);System.out.println(new String(by, 0, len));s.close();bi.close();bo.close();}}
import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.ServerSocket;import java.net.Socket;public class TCPserver {public static void main(String[] args) throws IOException {ServerSocket ss=new ServerSocket(4444);// 监听客户端System.out.println("服务器已经开启等待连接...");Socket accept = ss.accept();System.out.println("客户端连接成功");// 获取管道中的输入输出流InputStream is = accept.getInputStream();OutputStream os = accept.getOutputStream();// 包装管道中的输入流BufferedInputStream bi = new BufferedInputStream(is);BufferedOutputStream bo = new BufferedOutputStream(new FileOutputStream("E:\\new.jpg"));byte[] a = new byte[1024];int length = 0;while((length=bi.read(a))!=-1){bo.write(a, 0, length);bo.flush();}//给客户端反馈os.write("文件上传完毕".getBytes());bi.close();bo.close();}}


TCP多线程

import java.io.IOException;import java.net.ServerSocket;import java.net.Socket;public class TCPServer {public static void main(String[] args) throws IOException {//创建TCP服务器端的ServerSocket对象ServerSocket ss = new ServerSocket(6666);//监听客户端System.out.println("服务器已经开启,等待连接...");int cnt=1;while(true){Socket accept = ss.accept();//服务器会在这里等待连接System.out.println("第"+cnt+++"个客户端已建立连接");//开启子线程new TCPThread(accept).start();}}}
import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.FileWriter;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.net.Socket;public class TCPThread extends Thread {private Socket s ;public TCPThread(Socket s ) {this.s = s;}@Overridepublic void run() {try {//获取输入输出流对象InputStream is = s.getInputStream();OutputStream os = s.getOutputStream();//包装BufferedReader br = new BufferedReader(new InputStreamReader(is));BufferedWriter bw = new BufferedWriter(new FileWriter(Thread.currentThread().getName()+"new.txt"));//读取数据String line =null;while((line = br.readLine())!=null){bw.write(line);bw.newLine();bw.flush();}//给客户端反馈os.write("文件上传完毕".getBytes());} catch (Exception e) {e.printStackTrace();}}}
//客户端1import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.FileReader;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.io.OutputStreamWriter;import java.net.Socket;public class TCPClient {public static void main(String[] args) throws IOException {//1)创建TCP客户端的Socket对象Socket s = new Socket("192.168.100.2",6666);//2)获取输入输出流,写数据InputStream is = s.getInputStream();OutputStream os = s.getOutputStream();////包装BufferedReader br = new BufferedReader(new FileReader("测试.txt"));BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));//3)写数据String line = null;while((line=br.readLine())!=null){bw.write(line);bw.newLine();bw.flush();//要刷新!!!}//停止标志s.shutdownOutput();//读取反馈byte []a = new byte[1024];int len = is.read(a);System.out.println(new String(a, 0, len));//4)释放资源s.close();}
//客户端2import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.FileReader;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.io.OutputStreamWriter;import java.net.Socket;public class TCPClient2 {public static void main(String[] args) throws IOException {//1)创建TCP客户端的Socket对象Socket s = new Socket("192.168.100.2",6666);//2)获取输入输出流,写数据InputStream is = s.getInputStream();OutputStream os = s.getOutputStream();////包装BufferedReader br = new BufferedReader(new FileReader("测试2.txt"));BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));//3)写数据String line = null;while((line=br.readLine())!=null){bw.write(line);bw.newLine();bw.flush();//要刷新!!!}//停止标志s.shutdownOutput();//读取反馈byte []a = new byte[1024];int len = is.read(a);System.out.println(new String(a, 0, len));//4)释放资源s.close();}}