目录
二、InetAddress & InetScoketAddress
(一)InetAddress& InetScoketAddress相关概念
(二)InetAddress& InetScoketAddress常见方法
一、网络编程相关概念
网络编程:
- 把分布在不同地理区域的计算机专门的外部设备用通信线路互联成一个规模大、功能强的网络系统,从而使众多的计算机可以方便地互相传递信息、共享硬件、软件、数据信息等资源。
协议:
- TCP:TCP(Transmission Control Protocol,传输控制协议) 是一种面向连接的、可靠的、基于字节流的传输层通信协议,TCP 层是位于 IP 层之上,应用层之下的中间层。TCP 保障了两个应用程序之间的可靠通信。通常用于互联网协议,被称 TCP / IP。
- UDP:UDP (User Datagram Protocol,用户数据报协议),位于 OSI 模型的传输层。一个无连接的协议。提供了应用程序之间要发送数据的数据报。由于UDP缺乏可靠性且属于无连接协议,所以应用程序通常必须容许一些丢失、错误或重复的数据包。
IP地址:
- IP地址用来标识网络中的一个通信实体的地址,通信实体可以说计算机,路由器等。比如互联网中的每个服务器都要有自己的IP地址,而每个局域网的计算机要通信也要配置IP地址。
- IP地址=网络地址+主机地址
- IP地址分类:A类地址-1.0 B类地址-128.0 C类地址-192.0 D类地址-224.0
- 本机地址:127.0.0.1 or localhost
端口:
- 端口是虚拟的概念,并不是说主机上真的有端口。通过端口,可以在一个主机上运行多个网络应用程序。端口得到表示是一个16位的二进制整数,对应十进制0-65535.
- Oracle,MySQL,Tomcat,QQ,MSN,等网络程序都有自己的端口。
URL:
- 在互联网上每一信息资源都有统一且唯一的地址,改地址就叫做URL。URL由四个部分组成:协议,存放资源的主机域名,资源文件名和端口号。如果未指定该端口号,则使用的协议默认的端口。例如http协议的默认端口号80,在浏览器访问网页时,地址栏显示的地址就是URL。
数据报:
- 网络传输数据的基本单元,数据报 = 报头(header) + 数据。其中,报头:数据的目的地和其他数据之间的关系;
- UDP数据报的长度 = 报头 + 数据部分的总字节数。其中,报头的长度固定;
- 在用Socket编程时,UDP协议要求包小于64K,TCP没有限定。
数据包:
- 包(Packet)是TCP/IP协议通信传输中的数据单位,一般也称“数据包”。
套接字(Socket):
- 套接字是对网络中不同主机上的应用程序之间进行双向信的端点的抽象;
- 套接字上联应用进程,下联网络协议栈,是应用程序通过网络协议进行通信的接口,是应用程序与网络协议根进行交互的接口;
二、InetAddress & InetScoketAddress
(一)InetAddress& InetScoketAddress相关概念
InetAddress:封装IP和DNS
- Inet4Address:表示IPV4协议
- Inet6Address:表示IPV6协议
- 注:之前的IP地址,实际上是使用四个十进制数字表示,相当于32位,把这样的IP地址称为IPV4。但随着网络上的主机越来越多,之后发现IPV4地址不够使了,所以又进行改进,产生了IPV6。
InetSocketAddress:封装IP及端口。
(二)InetAddress& InetScoketAddress常见方法
- getLocalHost(): 获取本机的InetAddress对象;
- getHostAddress(): 获取ip地址;
- getHostName(): 获取计算机名;
- getByName(): 在给定主机名的情况下确定主机的 IP 地址;
- getByAddress(): 在给定原始 IP 地址的情况下,返回 InetAddress 对象;
(三)代码实例
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
public class Day38 {
public static void main(String[] args) throws UnknownHostException {
/* 本机InetAddress对象 */
InetAddress ia1 = InetAddress.getLocalHost(); // 获取本机的InetAddress对象
String local_ip = ia1.getHostAddress(); // 获取本机ip地址
String local_name = ia1.getHostName(); // 获取本机计算机名
System.out.println("本机ip: " + local_ip + ", 本机名: " + local_name);
/* 域名获取InetAddress对象 */
InetAddress ia2 = InetAddress.getByName("www.baidu.com");
String baidu_ip = ia2.getHostAddress(); // 获取baidu ip地址
String baidu_name = ia2.getHostName(); // 获取baidu 计算机名
System.out.println("baidu ip: " + baidu_ip + ", baidu名: " + baidu_name);
/* ip获取InetAddress对象 */
InetAddress ia3 = InetAddress.getByName("220.181.38.150");
String ip = ia3.getHostAddress(); // 获取ip地址
String name = ia3.getHostName(); // 获取计算机名
System.out.println("ip: " + ip + ", 名: " + name);
InetSocketAddress is = new InetSocketAddress("220.181.38.150", 200);
String name2 = is.getHostName(); // 获取主机名称
int port2 = is.getPort(); // 获得端口
InetAddress address = is.getAddress(); // 获取端口ip
System.out.println("name2: " + name2 + ", port2: " + port2 + ", 端口ip: " + address);
}
}
本机ip: ***.***.***.***, 本机名: ***
baidu ip: 220.181.38.150, baidu名: www.baidu.com
ip: 220.181.38.150, 名: 220.181.38.150
name2: 220.181.38.150, port2: 200, 端口ip: 220.181.38.150/220.181.38.150
三、URL
(一)URL相关概念
URL(Uniform Resource Locator)中文名为统一资源定位符,有时也被俗称为网页地址。表示为互联网上的资源,如网页或者 FTP 地址。
(二)URL类 & URLConnection类
URL类的相关方法
- URL类的构建方法
URL (String s) 构造一个 字符串 s 对象 URL URL(url,String s) 构造一个基本地址url和字符串s对象URL URL(String protocol,String host,String file) 构造指定的协议、主机名和文件名的URL 对象 URL(String protocol,String host,int port,String file) 构造指定的协议、主机名、端口号和文件名的URL 对象 - getProtocol():协议
- getAuthority():验证信息
- getFile():文件名及请求参数
- getHost():主机名
- getPath():路径
- getPort():端口
- getDefaultPort():默认端口
- getQuery():请求参数
- getRef():定位位置
URLConnections相关方法
openConnection() 返回一个 java.net.URLConnection:
-
如果你连接HTTP协议的URL, openConnection() 方法返回 HttpURLConnection 对象。
-
如果你连接的URL为一个 JAR 文件, openConnection() 方法将返回 JarURLConnection 对象。
-
...
- getContent():检索URL链接内容
- getContentEncoding():返回头部 content-encoding 字段值
- getContentLength():返回头部 content-length字段值
- getContentType():返回头部 content-type 字段值
- getLastModified():返回头部 last-modified 字段值
- getExpiration():返回头部 expires 字段值
- getIfModifiedSince():返回对象的 ifModifiedSince 字段值
- setDoInput(boolean input):URL 连接可用于输入和/或输出。如果打算使用 URL 连接进行输入,则将 DoInput 标志设置为 true;如果不打算使用,则设置为 false。默认值为 true。
- setDoOutput(boolean output):URL 连接可用于输入和/或输出。如果打算使用 URL 连接进行输出,则将 DoOutput 标志设置为 true;如果不打算使用,则设置为 false。默认值为 false。
- public InputStream getInputStream() throws IOException:返回URL的输入流,用于读取资源
- public OutputStream getOutputStream() throws IOException:返回URL的输出流, 用于写入资源。
- URL getURL():返回 URLConnection 对象连接的URL。
代码实例
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
public class day39 {
public static void main(String[] args){
// URL
try{
URL url = new URL("http://www.runoob.com/index.html?language=cn#j2se");
System.out.println("URL 为:" + url.toString());
System.out.println("协议为:" + url.getProtocol());
System.out.println("验证信息:" + url.getAuthority());
System.out.println("文件名及请求参数:" + url.getFile());
System.out.println("主机名:" + url.getHost());
System.out.println("路径:" + url.getPath());
System.out.println("端口:" + url.getPort());
System.out.println("默认端口:" + url.getDefaultPort());
System.out.println("请求参数:" + url.getQuery());
System.out.println("定位位置:" + url.getRef());
}catch (IOException e){
e.printStackTrace();
}
// URLConnection
try{
URL url2 = new URL("http://www.runoob.com/index.html?language=cn#j2se");
URLConnection urlcon = url2.openConnection();
HttpURLConnection connection = null;
if (urlcon instanceof HttpURLConnection){
connection = (HttpURLConnection) urlcon;
}else{
System.out.println("请输入url: ");
return;
}
BufferedReader in = new BufferedReader(
new InputStreamReader(urlcon.getInputStream())
);
String url_str = "";
String current;
while ((current = in.readLine()) != null){
url_str += current;
}
System.out.println(url_str);
}catch (IOException e){
e.printStackTrace();
}
}
}
URL 为:http://www.runoob.com/index.html?language=cn#j2se
协议为:http
验证信息:www.runoob.com
文件名及请求参数:/index.html?language=cn
主机名:www.runoob.com
路径:/index.html
端口:-1
默认端口:80
请求参数:language=cn
定位位置:j2se
<html><head><title>302 Found</title></head><body><center><h1>302 Found</h1></center><hr><center>JSP3/2.0.14</center></body></html>
(三)URLEncoder & URLDdcoder
URLDecoder类:
- 包含一个decode(String s,String charcter)静态方法,乱码的特殊字符串-->普通字符串。
URLEncoder类:
- 包含一个encode(String s,String charcter)静态方法,普通字符串-->特殊字符串
代码实例
import java.io.UnsupportedEncodingException;
public class Day40 {
public static void main(String[] args){
try{
String name = java.net.URLEncoder.encode("我爱Java!", "UTF-8");
System.out.println(name); // encode
System.out.println(java.net.URLDecoder.decode(name, "UTF-8")); // decode
name = java.net.URLEncoder.encode(name, "UTF-8");
System.out.println(name); // encode
name = java.net.URLDecoder.decode(name, "UTF-8");
System.out.println(name); //decode
System.out.println(java.net.URLDecoder.decode(name, "UTF-8"));
}catch (UnsupportedEncodingException e){
e.printStackTrace();
}
}
}
%E6%88%91%E7%88%B1Java%EF%BC%81
我爱Java!
%25E6%2588%2591%25E7%2588%25B1Java%25EF%25BC%2581
%E6%88%91%E7%88%B1Java%EF%BC%81
我爱Java!
四、TCP通信功能
TCP:TCP(Transmission Control Protocol,传输控制协议) 是一种面向连接的、可靠的、基于字节流的传输层通信协议,TCP 层是位于 IP 层之上,应用层之下的中间层。TCP 保障了两个应用程序之间的可靠通信。通常用于互联网协议,被称 TCP / IP。
在TCP连接中必须明确客户端与服务器端,由于客户端向服务器端发出连接请求,每次连接的创建都需要经过“三次握手”。
(一)TCP通信原理
1、原理:
- 在服务端指定一个端口号来创建ServerSocket,并使用accept方法进行侦听,这将阻塞服务器线程,等待用户请求;
- 在客户端指定服务的主机IP和端口号来创建socket,并连接服务端ServerSocket,此时服务端accept方法被唤醒,同时返回一个和客户端通信的socket;
- 在客户端和服务端分别使用socket来获取网络通信输入/输出流,并按照一定的通信协议对socket进行读/写操作;
- 通信完成后,在客户端和服务端中分别关闭socket。
- (此部分为引用,原文链接:https://blog.csdn.net/weixin_45851945/article/details/114263043)
2、ServerSocket
public ServerSocket(int port) throws IOException | 创建绑定到特定端口的服务器套接字 |
public ServerSocket(int port, int backlog) throws IOException | 利用指定的 backlog 创建服务器套接字并将其绑定到指定的本地端口号 |
public ServerSocket(int port, int backlog, InetAddress address) throws IOException | 使用指定的端口、侦听 backlog 和要绑定到的本地 IP 地址创建服务器 |
public ServerSocket() throws IOException | 创建非绑定服务器套接字 |
常用方法:
- getLocalPort():返回此套接字在其上侦听的端口
- accept():侦听并接受到此套接字的连接
- Timeout(int timeout): 通过指定超时值启用/禁用 SO_TIMEOUT,以毫秒为单位
- bind(SocketAddress host, int backlog):将 ServerSocket 绑定到特定地址(IP 地址和端口号)
3、socket
public Socket(String host, int port) throws UnknownHostException, IOException | 创建一个流套接字并将其连接到指定主机上的指定端口号。 |
public Socket(InetAddress host, int port) throws IOException | 创建一个流套接字并将其连接到指定 IP 地址的指定端口号 |
public Socket(String host, int port, InetAddress localAddress, int localPort) throws IOException | 创建一个套接字并将其连接到指定远程主机上的指定远程端口 |
public Socket(InetAddress host, int port, InetAddress localAddress, int localPort) throws IOException | 创建一个套接字并将其连接到指定远程地址上的指定远程端口 |
public Socket() | 通过系统默认类型的 SocketImpl 创建未连接套接字 |
常用方法:
- connect(SocketAddress host, int timeout):将此套接字连接到服务器,并指定一个超时值
- getInetAddress():返回套接字连接的地址
- getPort():返回此套接字连接到的远程端口
- getLocalPort():返回此套接字绑定到的本地端口
- getRemoteSocketAddress():返回此套接字连接的端点的地址,如果未连接则返回 null
- getInputStream():返回此套接字的输入流
- getOutputStream():返回此套接字的输出流
- close():关闭此套接字
(二)代码实例
1、TCP发送数据和接收数据
先运行服务端,再运行客户端
服务端:
// 服务器端
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDemo {
public static void main(String[] args) throws IOException {
// 创建服务器端的Socket对象(ServerSocket)
ServerSocket ss = new ServerSocket(10005);
// Socket accept(): 侦听要连接到此套接字并接受它
Socket s = ss.accept();
// 获取输入流,读数据,并把数据显示在控制台
InputStream is = s.getInputStream();
byte[] bys = new byte[1024];
int len = is.read(bys);
String data = new String(bys, 0, len);
System.out.println("服务器:" + data);
// 给出反馈
OutputStream os = s.getOutputStream();
os.write("数据已经收到".getBytes());
// 释放资源
ss.close();
}
}
客户端:
// 客户端
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class ClientDemo {
public static void main(String[] args) throws IOException {
// 创建客户端的Socket对象(Socket)
Socket s = new Socket("127.0.0.1", 10005);
// 获取输出流,写数据
OutputStream os = s.getOutputStream();
os.write("I love Java!".getBytes());
// 接收服务器反馈
InputStream is = s.getInputStream();
byte[] bys = new byte[1024];
int len = is.read(bys);
String data = new String(bys, 0, len);
System.out.println("客户端:" + data);
// 释放资源
s.close();
}
}
2、数据来自键盘输入,接收到的数据输出到控制台
服务端:
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 ServerDemo1 {
public static void main(String[] args) throws IOException{
ServerSocket ss = new ServerSocket(10005);
Socket s = ss.accept();
// 获得输入流
InputStream is = s.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null){
System.out.println(line);
}
ss.close();
}
}
客户端:
import java.io.*;
import java.net.Socket;
public class ClientDemo1 {
public static void main(String[] args) throws IOException {
Socket s = new Socket("127.0.0.1", 10005);
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
// 封装输出流对象,将字节输出流转为字符流
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
String line;
while((line = br.readLine()) != null){
if ("stop".equals(line)){
break;
}
bw.write(line);
bw.newLine();
bw.flush(); // 刷新缓冲流
}
s.close();
}
}