网络编程

2017/02/04 Java

网络编程

网络模型

  • OSI(Open System Interconnection开放系统互连)参考模型
  • TCP/IP参考模型

网络参考模型图

网络模型7层概述

  • 物理层:
    • 主要定义物理设备标准,如网线的接口类型、光纤的接口类型、各种传输介质的传输速率等。
    • 它的主要作用是传输比特流(就是由1、0转化为电流强弱来进行传输,到达目的地后在转化为1、0,也就是我们常说的数模转换与模数转换)。
    • 这一层的数据叫做比特。
  • 数据链路层:
    • 主要将从物理层接收的数据进行MAC地址(网卡的地址)的封装与解封装。
    • 在这一层工作的设备是交换机,数据通过交换机来传输。
    • 常把这一层的数据叫做帧。
  • 网络层:
    • 主要将从下层接收到的数据进行IP地址(例192.168.0.1)的封装与解封装。
    • 在这一层工作的设备是路由器,
    • 常把这一层的数据叫做数据包。
  • 传输层:
    • 定义了一些传输数据的协议和端口号(WWW端口80等)
      • TCP(传输控制协议,传输效率低,可靠性强,用于传输可靠性要求高,数据量大的数据)
      • UDP(用户数据报协议,与TCP特性恰恰相反,用于传输可靠性要求不高,数据量小的数据,如QQ聊天数据就是通过这种方式传输的)。
    • 主要是将从下层接收的数据进行分段和传输,到达目的地址后再进行重组。
    • 常常把这一层数据叫做段。
  • 会话层:
    • 通过传输层(端口号:传输端口与接收端口)建立数据传输的通路。
    • 主要在你的系统之间发起会话或者接受会话请求(设备之间需要互相认识可以是IP也可以是MAC或者是主机名)
  • 表示层:
    • 主要是进行对接收的数据进行解释、加密与解密、压缩与解压缩等(也就是把计算机能够识别的东西转换成人能够能识别的东西(如图片、声音等)。
  • 应用层:
    • 主要是一些终端的应用,比如说FTP(各种文件下载),WEB(IE浏览),QQ之类的(可以把它理解成我们在电脑屏幕上可以看到的东西.就是终端应用)。

网络通信三要素

  • IP地址:InetAddress
    • 网络中设备的标识,不易记忆,可用主机名
  • 端口号
    • 用于标识进程的逻辑地址,不同进程的标识
    • 是应用程序的标识。范围:0-65535。其中0-1024不建议使用。
  • 传输协议
    • 通讯的规则
      • 常见协议:TCP,UDP
// public static InetAddress getByName(String host)
// InetAddress address = InetAddress.getByName("liuyi");
// InetAddress address = InetAddress.getByName("192.168.12.92");
InetAddress address = InetAddress.getByName("192.168.12.63");

// 获取两个东西:主机名,IP地址
// public String getHostName()
String name = address.getHostName();
// public String getHostAddress()
String ip = address.getHostAddress();
IP地址:
	网络中计算机的唯一标识。
	
	计算机只能识别二进制的数据,所以我们的IP地址应该是一个二进制的数据。
	但是呢,我们配置的IP地址确不是二进制的,为什么呢?
		IP:192.168.1.100
		换算:11000000 10101000 00000001 01100100
	假如真是:11000000 10101000 00000001 01100100的话。
	我们如果每次再上课的时候要配置该IP地址,记忆起来就比较的麻烦。
	所以,为了方便表示IP地址,我们就把IP地址的每一个字节上的数据换算成十进制,然后用.分开来表示:
		"点分十进制"
		
	IP地址的组成:网络号段+主机号段
		A类:第一号段为网络号段+后三段的主机号段
			一个网络号:256*256*256 = 16777216
		B类:前二号段为网络号段+后二段的主机号段
			一个网络号:256*256 = 65536
		C类:前三号段为网络号段+后一段的主机号段
			一个网络号:256
	
	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	
			(1) 172.16.0.0---172.31.255.255是私有地址。
			(2) 169.254.X.X是保留地址。
		C类	192.0.0.1---223.255.255.254	
			(1) 192.168.X.X是私有地址
		D类	224.0.0.1---239.255.255.254 	
		E类	240.0.0.1---247.255.255.254
		
	两个DOS命令:
		ipconfig 查看本机ip地址
		ping 后面跟ip地址。测试本机与指定的ip地址间的通信是否有问题
		
	特殊的IP地址:
		127.0.0.1 回环地址(表示本机)
		x.x.x.255 广播地址
		x.x.x.0 网络地址

协议UDP和TCP

  • UDP
    • 将数据源和目的封装成数据包中,不需要建立连接;每个数据报的大小在限制在64k;因无连接,是不可靠协议;不需要建立连接,速度快
  • TCP
    • 建立连接,形成传输数据的通道;在连接中进行大数据量传输;通过三次握手完成连接,是可靠协议;必须建立连接,效率会稍低

Socket套接字

网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能识别的标识符套接字。

Socket原理机制:

  • 通信的两端都有Socket。
  • 网络通信其实就是Socket间的通信。
  • 数据在两个Socket间通过IO传输。

Socket机制图解

UDP

UDP协议发送和接收数据

  • 发送:
    • 创建UDP发送端的Socket对象
    • 创建数据并把数据打包
    • 发送数据
    • 释放资源
  • 接收:
    • 创建UDP接收端的Socket对象
    • 创建数据包用于接收数据
    • 接收数据
    • 解析数据包
    • 释放资源

UDP协议发送和接收数据图解

public class ReceiveThread implements Runnable {
	private DatagramSocket ds;

	public ReceiveThread(DatagramSocket ds) {
		this.ds = ds;
	}

	@Override
	public void run() {
		try {
			while (true) {
				// 创建一个包裹
				byte[] bys = new byte[1024];
				DatagramPacket dp = new DatagramPacket(bys, bys.length);

				// 接收数据
				ds.receive(dp);

				// 解析数据
				String ip = dp.getAddress().getHostAddress();
				String s = new String(dp.getData(), 0, dp.getLength());
				System.out.println("from " + ip + " data is : " + s);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
public class SendThread implements Runnable {
	private DatagramSocket ds;

	public SendThread(DatagramSocket ds) {
		this.ds = ds;
	}

	@Override
	public void run() {
		try {
			// 封装键盘录入数据
			BufferedReader br = new BufferedReader(new InputStreamReader(
					System.in));
			String line = null;
			while ((line = br.readLine()) != null) {
				if ("886".equals(line)) {
					break;
				}

				// 创建数据并打包
				byte[] bys = line.getBytes();
				// DatagramPacket dp = new DatagramPacket(bys, bys.length,
				// InetAddress.getByName("192.168.12.92"), 12345);
				DatagramPacket dp = new DatagramPacket(bys, bys.length,
						InetAddress.getByName("192.168.12.255"), 12306);

				// 发送数据
				ds.send(dp);
			}

			// 释放资源
			ds.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
public static void main(String[] args) throws IOException {
	DatagramSocket dsSend = new DatagramSocket();
	DatagramSocket dsReceive = new DatagramSocket(12306);

	SendThread st = new SendThread(dsSend);
	ReceiveThread rt = new ReceiveThread(dsReceive);

	Thread t1 = new Thread(st);
	Thread t2 = new Thread(rt);

	t1.start();
	t2.start();
}

TCP

TCP协议发送和接收数据

  • 发送:
    • 创建TCP客户端的Socket对象
    • 获取输出流,写数据
    • 释放资源
  • 接收:
    • 创建TCP服务器端的Socket对象
    • 监听客户端连接
    • 获取输入流,读取数据
    • 释放资源-

TCP协议发送和接收数据图解

// 创建客户端Socket对象
Socket s = new Socket("192.168.12.92", 11111);

// 封装文本文件
// BufferedReader br = new BufferedReader(new FileReader(
// "InetAddressDemo.java"));
BufferedReader br = new BufferedReader(new FileReader(
		"ReceiveDemo.java"));
// 封装通道内流
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
		s.getOutputStream()));

String line = null;
while ((line = br.readLine()) != null) { // 阻塞
	bw.write(line);
	bw.newLine();
	bw.flush();
}

// Socket提供了一个终止,它会通知服务器你别等了,我没有数据过来了
s.shutdownOutput();

// 接收反馈
BufferedReader brClient = new BufferedReader(new InputStreamReader(
		s.getInputStream()));
String client = brClient.readLine(); // 阻塞
System.out.println(client);

// 释放资源
br.close();
s.close();
public class UserThread implements Runnable {
	private Socket s;

	public UserThread(Socket s) {
		this.s = s;
	}

	@Override
	public void run() {
		try {
			// 封装通道内的流
			BufferedReader br = new BufferedReader(new InputStreamReader(
					s.getInputStream()));
			// 封装文本文件
			// BufferedWriter bw = new BufferedWriter(new
			// FileWriter("Copy.java"));

			// 为了防止名称冲突
			String newName = System.currentTimeMillis() + ".java";
			BufferedWriter bw = new BufferedWriter(new FileWriter(newName));

			String line = null;
			while ((line = br.readLine()) != null) { // 阻塞
				bw.write(line);
				bw.newLine();
				bw.flush();
			}

			// 给出反馈
			BufferedWriter bwServer = new BufferedWriter(
					new OutputStreamWriter(s.getOutputStream()));
			bwServer.write("文件上传成功");
			bwServer.newLine();
			bwServer.flush();

			// 释放资源
			bw.close();
			s.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
ServerSocket ss = new ServerSocket(11111);

while (true) {
	Socket s = ss.accept();
	new Thread(new UserThread(s)).start();
}

以上概念总结于传智播客Java基础课程

Search

    Post Directory