网络基础知识
基本概念
网络编程:不需要依赖浏览器进行通讯.,例如QQ。
网页编程:浏览器与服务器之间的通讯。
计算机网络:指分布在不同地域的计算机,通过外部设备连接起来,实现了资源共享与数据传输的计算机系统。
DHCP:(Dynamic Host Configuration Protocol,动态主机配置协议)是一个局域网的网络协议,使用UDP协议工作, 主要有两个用途:给内部网络或网络服务供应商自动分配IP地址,给用户或者内部网络管理员作为对所有计算机作中央管理的手段,在RFC 2131中有详细的描述。
在DHCP客户端手工释放IP地址命令为ipconfig /release;
更新IP地址命令为ipconfig /renew。
OSI网络互联七层框架与TCP/IP协议族(栈)五层网络架构
OSI(Open System Interconnect),即开放式系统互联,一般叫做OSI参考模型。
OSI层 | 功能 | 数据单元 | 封装、解封装过程 (浏览网站为例) | 比喻 (邮递服务为例) | TCP/IP协议族(栈) | |||
应用层 Application Layer | 文件传输,电子邮件,文件服务,虚拟终端 | data (数据) | 生成请求头 | 解析请求头 | 经理:写好信件草稿 | 经理:阅读信件 | HTTP,HTTPS,FTP,TELNET,DNS,SSH,TFTP,SMTP,SNMP,POP3 | |
表示层 Presentation Layer | 数据格式化,代码转换,数据加密,数据压缩 | 转换成为计算机可识别的ASCII码 | 转换成请求头 | 助理:修改错字或格式 | 助理:提醒经理有信,翻译内容 | 没有协议 | ||
会话层 Session Layer | 解除或建立与别的接点的联系 | 产生相应的主机进程 | 秘书:找出收信人地址,写好信封 | 秘书:拆信,制作副本 | 没有协议 | |||
传输层 Transport Layer | 提供端对端的接口 | segment (数据段) | 加上相应的端口号信息 | 匹配端口号 | 司机:寄信 | 司机:取信 | TCP,UDP | 四层交换机、也有工作在四层的路由器 |
网络层 Network Layer | 为数据包选择路由 | packet (数据包) | 加上IP地址 | 匹配IP地址 | 分拣工:分拣 | 分拣工:分拣 | IP,ICMP,RIP,OSPF,BGP,IGMP | 路由器、三层交换机 |
数据链路层 Data Link Layer | 传输有地址的帧以及错误检测功能 | frame (数据帧) | 加上MAC地址 | 匹配MAC地址 | 包装工:打包装箱 | 拆包工:开箱拆包 | SLIP,CSLIP,PPP,ARP,RARP,MTU | 网桥(现已很少使用)、以太网交换机(二层交换机)、网卡(其实网卡是一半工作在物理层,一半工作在数据链路层) |
物理层 Physical Layer | 以二进制数据形式在物理媒体上传输数据 | bits (比特流) | 转成bit流信息 | 转换成为计算机可识别的ASCII码 | 搬运工:将货搬上车 | 搬运工:将货搬下车 | ISO2110,IEEE802,IEEE802.2 | 中继器、集线器、双绞线、网线、网卡 |
计算机网络通讯三要素:IP地址、端口号、通讯协议
IP地址
IP地址用来标识计算机,本质由32位二进制位数组成,为方便记录,把IP地址分成了4段,每段8个二进制数据用十进制表示。范围:2^8 = 0~255
IP地址 = 网络地址 + 主机地址
IP地址的类别(总共5类,常用3类):
IP地址类别 | A类地址 | B类地址 | C类地址 |
IP地址结构 | 一个网络地址 + 三个主机地址 | 两个网络地址 + 两个主机地址 | 三个网络地址 + 一个主机地址 |
IP地址范围 | 0.0.0.0-127.255.255.255 | 128.0.0.0-191.255.255.255 | 192.0.0.0-223.255.255.255 |
私有IP地址范围 | 10.0.0.0-10.255.255.255 | 172.16.0.0-172.31.255.255 | 192.168.0.0-192.168.255.255 |
保留地址范围 | 127.0.0.0~127.255.255.255 | 169.254.0.0~169.254.255.255 | 无 |
一个公共地址最大主机数 (主机号的各位不能同时为0,1)) | 16777214(2^24-2) | 65534(2^16-2) | 254(2^8-2) |
默认子网掩码 | 255.0.0.0 | 255.255.0.0 | 255.255.255.0 |
用途 | 政府 | 学校、事业单位 |
端口号
端口号用来标识计算机的进程。端口号的范围:0-65535
从0到1023,为系统所保留。自定义端口建议选1024 到 65535。
win7防火墙怎么设定开放端口:
1. 【控制面板】 -> 【windows防火墙】 -> 左侧【高级设置】 -> 左侧【入站规则】 -> 右侧【新建规则】:
2. 选中【端口】点击下一步。
3. 选中【TCP】并选中【特定本地端口】在后面的输入框中输入端口号,点击下一步。
4. 选中【允许连接】点击下一步。
5. 选择规则应用的网络,默认是全部选中的,采用默认即可,点击下一步。
6. 为新建的规则起名并做相应的描述,点击完成。
7. 返回【高级设置】,左侧【入站规则】按出站规则的设置类似操作。
通讯协议:Udp协议、tcp协议
含义 | 连接机制&数据可靠性 | 数据量 | 效率 | 用例 | |
UDP协议 | User Datagram Protocol,用户数据报协议 | 无连接的不可靠的传输协议:每个数据报都是一个独立的信息,包括完整的源地址或目的地址,因此不需建立发送方和接收方的连接。数据报无序易丢失。不可靠。它在网络上以任何可能的路径传往目的地,因此能否到达目的地,到达目的地的时间以及内容的正确性都是不能被保证的。 | 每个数据报大小限制在64K | 效率高 | 对讲机、QQ通讯、cs游戏、视频会议 |
TCP协议 | Transfer Control Protocol,传输控制协议 | 面向连接的可靠的传输协议:socket之间通过三次握手机制连接,双向数据传输,双方都可以进行发送或接收操作。数据流可靠有序无差错,有特有的通道,以字节流方式发送数据。HTTP、FTP、Telnet等应用都需要这种可靠的通信通道 | 传输大数据量 | 效率低 | 打电话、QQ文件传输 |
URL类
java.net.URL
URL:统一资源定位符
URL由两部分组成:协议名称和资源名称,中间用冒号隔开。
例子:http://localhost:8080/myweb/test.html
http://:http协议。执行流程:在本地hosts文件(在C:\Windows\System32\drivers\etc\)找域名所对应ip,如果找不到,联网去网络运营商的DNS服务器找,找到后访问该ip地址对应的服务器。
localhost:本地域名。(外地域名如www.baidu.com)。
8080:软件监听端口,定位具体的一个软件。(Tomcat:8080;mysql:3306;oracle:1521;系统默认80,URL中可不写)
myweb:web应用的名称(根目录)。
test.html:web应用的资源。
与URI(统一资源标识符)和URN(统一资源名)的区别:
URI 可以进一步分为定位器(URL)、名称(URN),或者二者兼具。
有访问机制的URI也是URL。
URI可以描述任何文件:本地的,互联网上的;URL描述互联网上的(???)
request.getRequestURL() 得到的是 scheme://host.domain:port/path/filename
request.getRequestURI() 得到的是 /path/filename
常用scheme:http、https、ftp(文件传输协议)、mailto、file(计算机上的文件)
URL类常用方法
import java.net.MalformedURLException; import java.net.URL; public class TestURL { public static void main(String[] args) { try { // 构造方法 URL baidu = new URL("http://www.baidu.com"); // http://www.baidu.com(协议一定要带上,和InetAddress不一样) URL index = new URL(baidu, "/index?name=twx#test");// http://www.baidu.com/index?name=twx#test // 获取URL的信息 System.out.println(index.getProtocol()); // 获取协议: http System.out.println(index.getHost()); // 获取主机: www.baidu.com System.out.println(index.getPort()); // 获取端口: -1(默认80端口返回值是-1) System.out.println(index.getPath()); // 获取文件路径: /index System.out.println(index.getFile()); // 获取文件名: /index?name=twx System.out.println(index.getQuery()); // 获取查询字符串: name=twx System.out.println(index.getRef()); // 获取锚点: test } catch (MalformedURLException e) { e.printStackTrace(); } } } |
用 URL 类的 openStream() 或 openConnection() 方法获取页面源代码
package com.tongwx.network; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.MalformedURLException; import java.net.URL; public class GetSource { public static void main(String[] args) throws IOException { getSourceByCharacterStream(); getSourceByByteStream(); } /** * 用字符流方式获取 */ private static void getSourceByCharacterStream() throws IOException { URL url = new URL("https://www.google.com");//协议一定要带上,这不是浏览器输地址! BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(url.openStream(), "utf-8"));//乱码未解决 BufferedWriter bufferedWriter = new BufferedWriter( new OutputStreamWriter(new FileOutputStream("E:/google.html"), "utf-8"));//乱码未解决 String str; while (null != (str = bufferedReader.readLine())) { bufferedWriter.write(str); } bufferedReader.close(); bufferedWriter.close(); } /** * 用字节流方式获取 */ private static void getSourceByByteStream() throws MalformedURLException, IOException, FileNotFoundException { URL url = new URL("https://www.baidu.com");//协议一定要带上,这不是浏览器输地址! InputStream inputStream = url.openStream();//相当于url.openConnection().getInputStream(); FileOutputStream fileOutputStream = new FileOutputStream("E:/baidu.html"); byte[] bs = new byte[2048]; int length; while (-1 != (length = inputStream.read(bs, 0, bs.length))) { fileOutputStream.write(bs, 0, length);//https://www.google.com乱码未解决 } inputStream.close(); fileOutputStream.close(); } } |
package com.tongwx.littleutils; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.URL; import java.net.URLConnection; import java.util.List; import java.util.Map; public class HttpRequest { public static void main(String[] args) { //发送 GET 请求 String s=HttpRequest.sendGet("http://localhost:6144/Home/RequestString", "key=123&v=456"); System.out.println(s);
//发送 POST 请求 String sr=HttpRequest.sendPost("http://localhost:6144/Home/RequestPostString", "key=123&v=456"); System.out.println(sr); } /** * 向指定URL发送GET方法的请求 * * @param url * 发送请求的URL * @param param * 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 * @return URL 所代表远程资源的响应结果 */ public static String sendGet(String url, String param) { String result = ""; BufferedReader in = null; try { String urlNameString = url + "?" + param; URL realUrl = new URL(urlNameString); // 打开和URL之间的连接 URLConnection connection = realUrl.openConnection(); // 设置通用的请求属性 connection.setRequestProperty("accept", "*/*"); connection.setRequestProperty("connection", "Keep-Alive"); connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); // 建立实际的连接 connection.connect(); // 获取所有响应头字段 Map<String, List<String>> map = connection.getHeaderFields(); // 遍历所有的响应头字段 for (String key : map.keySet()) { System.out.println(key + "--->" + map.get(key)); } // 定义 BufferedReader输入流来读取URL的响应 in = new BufferedReader(new InputStreamReader( connection.getInputStream())); String line; while ((line = in.readLine()) != null) { result += line; } } catch (Exception e) { System.out.println("发送GET请求出现异常!" + e); e.printStackTrace(); } // 使用finally块来关闭输入流 finally { try { if (in != null) { in.close(); } } catch (Exception e2) { e2.printStackTrace(); } } return result; } /** * 向指定 URL 发送POST方法的请求 * * @param url * 发送请求的 URL * @param param * 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 * @return 所代表远程资源的响应结果 */ public static String sendPost(String url, String param) { PrintWriter out = null; BufferedReader in = null; String result = ""; try { URL realUrl = new URL(url); // 打开和URL之间的连接 URLConnection conn = realUrl.openConnection(); // 设置通用的请求属性 conn.setRequestProperty("accept", "*/*"); conn.setRequestProperty("connection", "Keep-Alive"); conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); // 发送POST请求必须设置如下两行 conn.setDoOutput(true); conn.setDoInput(true); // 获取URLConnection对象对应的输出流 out = new PrintWriter(conn.getOutputStream()); // 发送请求参数 out.print(param); // flush输出流的缓冲 out.flush(); // 定义BufferedReader输入流来读取URL的响应 in = new BufferedReader( new InputStreamReader(conn.getInputStream())); String line; while ((line = in.readLine()) != null) { result += line; } } catch (Exception e) { System.out.println("发送 POST 请求出现异常!"+e); e.printStackTrace(); } //使用finally块来关闭输出流、输入流 finally{ try{ if(out!=null){ out.close(); } if(in!=null){ in.close(); } } catch(IOException ex){ ex.printStackTrace(); } } return result; } } |
下载文件
import com.google.common.collect.Lists; |
TCP编程(Socket)
什么是Socket
Socket(套接字)是连接运行在网络上的两个程序间的双向通讯的端点。
使用Socket进行网络通信的实现步骤
|
|
案例:使用基于TCP协议的Socket通信
package com.tongwx.network; 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; | package com.tongwx.network; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.Socket; |
public class TcpServer { public static void main(String[] args) throws IOException { ServerSocket serverSocket = new ServerSocket(5000); while (true) { //监听客户端请求,一旦连接返回新socket对象 Socket socket = serverSocket.accept(); new ServerInputThread(socket).start(); new ServerOtuputThread(socket).start(); } } } | public class TcpClient { public static void main(String[] args) throws IOException { Socket socket = new Socket("localhost", 5000); new ClientOutputThread(socket).start(); new ClientInputThread(socket).start(); } } |
class ServerInputThread extends Thread { private Socket socket; public ServerInputThread(Socket socket) { this.socket = socket; } @Override public void run() { try { InputStream inputStream = socket.getInputStream(); byte[] bs = new byte[200]; int readLength; while (true) { readLength = inputStream.read(bs); String message = new String(bs, 0, readLength); System.out.println(message); // //以下方式出错,不知为何 // byte[] bs = new byte[200]; // int realLength; // while (-1 != (realLength = inputStream.read(bs, 0, bs.length))) { // System.out.println(new String(bs, 0, realLength)); // } if ("EXIT".equals(message.toUpperCase())) { inputStream.close(); socket.close(); } } } catch (IOException e) { e.printStackTrace(); } } } | class ClientInputThread extends Thread { private Socket socket; public ClientInputThread(Socket socket) { this.socket = socket; } @Override public void run() { try { InputStream inputStream = socket.getInputStream(); byte[] bs = new byte[200]; int readLength; while (true) { readLength = inputStream.read(bs); String message = new String(bs, 0, readLength); System.out.println(message); // //以下方式出错,不知为何 // byte[] bs = new byte[200]; // int realLength; // while (-1 != (realLength = inputStream.read(bs, 0, bs.length))) { // System.out.println(new String(bs, 0, realLength)); // } if ("EXIT".equals(message.toUpperCase())) { inputStream.close(); socket.close(); } } } catch (IOException e) { e.printStackTrace(); } } } |
class ServerOtuputThread extends Thread { private Socket socket; public ServerOtuputThread(Socket socket) { this.socket = socket; } @Override public void run() { try { OutputStream outputStream = socket.getOutputStream(); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in)); while (true) { String readLine = bufferedReader.readLine(); outputStream.write(readLine.getBytes()); if ("EXIT".equals(readLine.toUpperCase())) { outputStream.close(); socket.close(); } } } catch (IOException e) { e.printStackTrace(); } } } | class ClientOutputThread extends Thread { private Socket socket; public ClientOutputThread(Socket socket) { this.socket = socket; } @Override public void run() { try { OutputStream outputStream = socket.getOutputStream(); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in)); while (true) { String readLine = bufferedReader.readLine(); outputStream.write(readLine.getBytes()); if ("EXIT".equals(readLine.toUpperCase())) { outputStream.close(); socket.close(); } } } catch (IOException e) { e.printStackTrace(); } } } |
InetAddress类
java.net.InetAddress
InetAddress(IP地址类)常用方法(没有构造方法,用静态方法获取实例):
获取InetAddress实例 | ||
static InetAddress | getLocalHost() | 获取本地的IP地址(InetAddress实例)。 |
static InetAddress | getByName(String host) | 获取指定主机名的IP地址。如果提供IP地址字符串,则仅检查地址格式的有效性。 |
static InetAddress[] | getAllByName(String host) | 获取指定域名的IP地址数组。 |
获取InetAddress实例的信息 | ||
String | getHostName() | 获取此IP地址的主机名。 |
String | getHostAddress() | 获取此IP地址的字符串形式。 |
byte[] | 获取此IP地址的字节数组形式。 |
代码示例
import java.net.InetAddress; import java.net.UnknownHostException; public class IPDemo { public static void main(String[] args) throws UnknownHostException { // 获取IP地址(InetAddress实例)的方法 InetAddress localHost = InetAddress.getLocalHost();// 获取本机IP地址(InetAddress实例):TWX/192.168.183.1 InetAddress byName = InetAddress.getByName("TWX");// 根据主机名获取IP地址:TWX/192.168.183.1 InetAddress byName = InetAddress.getByName("www.baidu.com");//www.baidu.com/103.235.46.39(不要带协议,和URL不一样) InetAddress byAddress = InetAddress.getByName("192.168.183.123");// 检查IP地址字符串格式有效性:/192.168.183.123 InetAddress[] allByName = InetAddress.getAllByName("java.sun.com");// 根据域名获取IP地址数组:{java.sun.com/156.151.59.19} // 获取IP地址(InetAddress实例)信息的方法 String hostName = InetAddress.getLocalHost().getHostName();// 获取本机IP地址主机名:TWX String hostAddress = InetAddress.getLocalHost().getHostAddress();// 获取本机IP地址字符串:192.168.183.1 byte[] hostAddressBytes = InetAddress.getLocalHost().getAddress();// 获取本机IP地址的字节数组。 System.out.println(Arrays.toString(hostAddressBytes));// [-64, -88, -73, 1] } } |
UDP编程(DataGram)
案例
package com.tongwx.network; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; public class UdpClient2 { public static void main(String[] args) throws IOException { //接收 DatagramSocket datagramSocket = new DatagramSocket(7000); byte[] bs = new byte[1000]; DatagramPacket datagramPacket = new DatagramPacket(bs, 1000); datagramSocket.receive(datagramPacket); System.out.println(new String(bs, 0, datagramPacket.getLength())); //回复 String reply = "一曲菱歌敌万金!"; datagramPacket = new DatagramPacket(reply.getBytes(), reply.getBytes().length, datagramPacket.getAddress(), datagramPacket.getPort());//注意:str.length() 不一定等于 str.getBytes().length datagramSocket.send(datagramPacket); datagramSocket.close(); } } |
package com.tongwx.network; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; public class UDPClient1 { public static void main(String[] args) throws IOException { //发送 DatagramSocket datagramSocket = new DatagramSocket(); String message = "画眉深浅入时无?"; DatagramPacket datagramPacket = new DatagramPacket(message.getBytes(), message.getBytes().length, InetAddress.getByName("localhost"), 7000);//注意:str.length() 不一定等于 str.getBytes().length datagramSocket.send(datagramPacket); //接收 byte[] bs = new byte[1000]; datagramPacket = new DatagramPacket(bs, 1000); datagramSocket.receive(datagramPacket); System.out.println(new String(bs, 0, datagramPacket.getLength())); datagramSocket.close(); } } |