《疯狂java讲义》读书笔记(八):网络编程

《疯狂java讲义》读书笔记(八):网络编程

网络编程的一些基础在本篇读书笔记中较少涉及,在理解TCP和UDP的时候,最好还是有些知识储备,这学期学完了计算机网络,再看一遍书,又加深了印象。

​ 关于网络编程这块儿,书上很多都是例子为主,在这一节的读书笔记,结合大二学的一些东西和大三学的一些专业课来写,并不是完全意义上的《疯狂java讲义》读书笔记。

​ 在这节的读书笔记里,主要从3个方面去介绍,分别是网络基础、Java网络API以及基于TCP的网络编程,在李刚的这本书中,除了基于TCP的网络编程还讲了基于UDP的网络编程,有兴趣的读者可以自行去翻阅,这里不花篇幅去介绍了。

1.网络基础

​ 学过计算机网络的话,对于TCP/IP协议、IP地址和端口以及域名和DNS应该都有所了解,可以直接看第二部分了。

1.1 网络类型

​ 这部分很简单,无非是可以按照规模大小地理位置分为局域网、城域网和广域网,还有按照网络的拓扑结构可以分为星型网络、网状网络等知识内容。

1.2 TCP/IP协议

​ 目前局域网采用的协议标准是TCP/IP协议。TCP/IP不是一个协议,而是一个协议族的统称。里面包括了IP协议,IMCP协议,TCP协议,以及我们更加熟悉的http、ftp、pop3协议等等。电脑有了这些,就好像学会了外语一样,就可以和其他的计算机终端做自由的交流了。

1.3 IP地址和端口

​ IP地址是因特网上的主机和路由器所使用的地址,用于标识网编号的主机编号,IP地址被分为A-E 5类。A、B、C类比较常用。

​ 端口号是应用程序和外界交流的出入口,用于表示数据交给哪个通信程序进行处理,意思就是说信息从主机A发到了目的主机B,主机B上运行着非常多的程序,而主机A的意图是想把信息发给主机B上的某一个程序,那么怎么区分这么多程序呢,就需要端口号来辨别。IP地址相当于门牌号,主机A想找到主机B,就得靠主机B的IP地址在大千世界里才能找到。

​ 其中,我们常见的80端口号就是HTTP服务端口号,以后还会见到各种花里胡哨的端口号。

​ 关于IP地址和端口号在计算机网络中会详细学,在这里不多说了。

1.4 域名

​ 网络通信中,路由器使用定长且包含网络地址信息的IP地址进行路由。收发数据必须利用IP地址。IP地址不方便记忆,因此必须用更友好的、便于记忆的名字来代替数字 IP 地址"。这个名字就是域名。DNS是用于把域名解析成IP地址的。

2.Java网络API
2.1InetAddress类

​ 该类适用于封装IP地址或域名的,没有构造方法所以不能直接创建对象。

import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;

public class InetAddressDemo {

	public static void main(String[] args) {

		try {
			// 获取本机地址信息
			InetAddress localIp = InetAddress.getLocalHost();
			System.out.println("localIp.getCanonicalHostName()= "
					+ localIp.getCanonicalHostName());
			System.out.println("localIp.getHostAddress()= "
					+ localIp.getHostAddress());
			System.out.println("localIp.getHostName()= "
					+ localIp.getHostName());
			System.out.println("localIp.toString()= " + localIp.toString());
			System.out.println("localIp.isReachable(5000)= "
					+ localIp.isReachable(5000));
			System.out.println("====================================");

			// 获取指定域名地址信息
			InetAddress baiduIp = InetAddress.getByName("www.baidu.com");
			System.out.println("baiduIp.getCanonicalHostName()= "
					+ baiduIp.getCanonicalHostName());
			System.out.println("baiduIp.getHostAddress()= "
					+ baiduIp.getHostAddress());
			System.out.println("baiduIp.getHostName()= "
					+ baiduIp.getHostName());
			System.out.println("baiduIp.toString()= " + baiduIp.toString());
			System.out.println("baiduIp.isReachable(5000)= "
					+ baiduIp.isReachable(5000));
			System.out.println("====================================");

			// 获取指定原始IP地址信息
			// InetAddress ip = InetAddress
			// .getByAddress(new byte[] { 127, 0, 0, 1 });
			InetAddress ip = InetAddress.getByName("127.0.0.1");
			System.out.println("ip.getCanonicalHostName()= "
					+ ip.getCanonicalHostName());
			System.out.println("ip.getHostAddress()= " + ip.getHostAddress());
			System.out.println("ip.getHostName()= " + ip.getHostName());
			System.out.println("ip.toString()= " + ip.toString());
			System.out.println("ip.isReachable(5000)= " + ip.isReachable(5000));
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}
2.2URL类

protocal://host:port/resourceName,这就是个URL的组成结构。

​ 比如说http://book.mooc.cn/java-book.html。默认端口80是可以省略的。

import java.net.MalformedURLException;
import java.net.URL;


public class URLDemo {

	public static void main(String[] args) {
		try {
			URL mybook = new URL("https://blog.csdn.net/weixin_40992982");
			System.out.println("协议protocol=" + mybook.getProtocol());
			System.out.println("主机host =" + mybook.getHost());
			System.out.println("端口port=" + mybook.getPort());
			System.out.println("文件filename=" + mybook.getFile());
			System.out.println("锚ref=" + mybook.getRef());
			System.out.println("查询信息query=" + mybook.getQuery());
			System.out.println("路径path=" + mybook.getPath());
		} catch (MalformedURLException e) {
			e.printStackTrace();
		}
	}

}
2.3URLConnection类

​ URLConnection代表与URL指定的数据源的动态链接。

2.4URLDecoder和URLEncoder类

​ 涉及到普通字符串和application/x-www-form-urlencoded MIME字符串之间相互转换时需要使用URLDecoder和URLEncoder两个工具类。

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;

public class URLDecoderDemo {

	public static void main(String[] args) {
		try {
			// 将普通字符串转换成application/x-www-form-urlencoded字符串
			String urlStr = URLEncoder.encode("Hello,这里是NayelyA", "GBK");
			System.out.println(urlStr);

			// 将application/x-www-form-urlencoded字符串 转换成普通字符串
			String keyWord = URLDecoder.decode(
					"Hello%2C%D5%E2%C0%EF%CA%C7NayelyA", "GBK");
			System.out.println(keyWord);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}

	}

}
3.基于TCP的网络编程

​ java.net包中提供了网络编程所需要的类,其中基于TCP协议的网络编程主要使用两种Socket,一个是ServerSocket(服务器套接字)还有一个是Socket(客户端套接字)

3.1 ServerSocket 类主要方法:

​ 运行在服务器端,监听来自客户端的Socket连接。

Socket accept(); // 如果接受到一个客户端Socket的连接请求,该方法将会返回一个与客户端Socket对应的Socket。
ServerSocket(int port) // 用指定端口 port 来创建一个 ServerSocket ,0-65535。构造方法还有别的,在这里不全写出来了。

​ ServerSocket 使用完毕后应使用其 close方法关闭该 ServerSocket ,通常情况下,服务器不应该只接受一个客户端请求,所以 java 程序通常会通过循环不停调用和 accept() 方法。

​ 使用ServerSocket进行网络通信的具体步骤。

1)根据指定的端口号来实例化一个ServerSocket对象

2)调用ServerSocket对象的accept()方法接收客户端发送的Socket对象

3)调用Socket对象的getInputStream()/getOutputStream()方法建立和客户端进行交互的IO流

4)关闭服务器端的Socket

5)回到第二步,继续监听

示例代码:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerSocketDemo extends Thread {
	// 声明一个ServerSocket
	ServerSocket server;
	// 计数
	int num = 0;

	public ServerSocketDemo() {
		// 创建ServerSocket,用于监听28888端口是否有客户端的Socket
		try {
			server = new ServerSocket(28888);
		} catch (IOException e) {
			e.printStackTrace();
		}
		// 启动当前线程,即执行run()方法
		this.start();
		System.out.println("服务器启动...");
	}
	@Override
	public void run() {
		while (this.isAlive()) {
			try {
				// 接收客户端的Socket
				Socket socket = server.accept();
				// 将Socket对应的输入流包装成BufferedReader
				BufferedReader br = new BufferedReader(new InputStreamReader(
						socket.getInputStream()));
				// 读客户端发送的信息并显示
				String line = br.readLine();
				System.out.println(line);

				// 将Socket对应的输出流包装成PrintStream
				PrintStream ps = new PrintStream(socket.getOutputStream());
				// 往客户端发送信息
				ps.println("您是第" + (++num) + "个访问服务器的用户!");
				ps.flush();

				// 关闭
				br.close();
				ps.close();
				socket.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	public static void main(String[] args) {
		new ServerSocketDemo();
	}
}
3.2 Socket 类主要方法:
Socket(InetAddress/String remoteAddress, int port); 
// 创建连接到指定远程主机,远程端口的 Socket,该构造器没有指定本地地址、本地端口,默认使用本地主机的默认 IP 地址,默认使用系统动态分配的端口。
Socket(InetAddress/String remoteAddress, int port, InetAddress localAddr, int localPort); 
// 创建连接到指定远程主机、远程端口的 Socket, 并指定本地 IP 地址和本地端口,使用与本地主机有多个 IP 地址的情况。
InputStream getInputStream(); 
// 返回该 Socket 对象对应的输入流,让程序通过该输入流从Socket中取出数据。
OutputStream getOutputStream();
// 返回该 Socket 对象对应的输出流,让程序通过该输出流向Socket中输出数据。

​ Socket的两个构造方法都需要声明抛出IOException异常。使用Socket进行通信的步骤是:

1)根据指定IP地址和端口号创建一个Socket对象

2)调用getInputStream()或者getOutputStream()方法打开连接到Socket的输入/出流

3)关闭Socket

示例代码:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;

public class ClientSocketDemo {

	public static void main(String[] args) {
		try {
			//创建连接到本机、端口为28888的Socket对象
			Socket socket = new Socket("127.0.0.1", 28888);
			// 将Socket对应的输出流包装成PrintStream
			PrintStream ps = new PrintStream(socket.getOutputStream());
			// 往服务器发送信息
			ps.println("我是NayelyA");
			ps.flush();

			// 将Socket对应的输入流包装成BufferedReader
			BufferedReader br = new BufferedReader(new InputStreamReader(
					socket.getInputStream()));
			// 读服务器返回的信息并显示
			String line = br.readLine();
			System.out.println("来自服务器的数据:" + line);

			// 关闭
			br.close();
			ps.close();
			socket.close();
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
3.3 Socket通信模型

​ 图源网络。

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值