相关知识点:
Transient:Java中的关键字,只能修饰变量,不能修饰类和方法。
作用:使被修饰的变量无法被序列化。
拓展:一个静态变量,无论是否被transient修饰都无法被序列化。若静态变量反序列化得到相应的值,可能是由于jvm中存在与静态变量相同名的静态变量,值是jvm中与静态变量相同名的静态变量的值。
若一个类实现了serializable,则其中的非静态变量和非transient修饰的变量都会被自动序列化;若类实现的是Externalizable接口,则没有任何东西可以自动序列化,需要在writeExternal方法中进行手工指定所要序列化的变量,这与是否被transient修饰无关。
String[] args:在main方法中,args用来存放传入的参数,dos中编程时,可在字节码文件之后设置传入的参数。
InetAddress类使用介绍:
相关方法演示如下:
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
public class InetAddressTest {
public static void main(String[] args) throws IOException {
//以百度为例,生成Inetaddress对象
//通过百度名:www.baidu.com获取对象
InetAddress hosts=InetAddress.getByName("www.baidu.com");
//打印hosts内容
System.out.println("百度的地址为:"+hosts);
//获取百度的主机名
System.out.println("百度的主机名为:"+hosts.getHostName());
//获取百度的原始ip地址
System.out.println("百度的ip地址为:"+hosts.getHostAddress());
//判断在3000ms内,百度是否允许访问
System.out.println("3000ms内,百度是否允许访问:"+hosts.isReachable(3000));
//InetAddress 的localhost()方法,都为获取本地的主机地址
}
}
运行结果如下所示:
UDP相关知识点:
UDP:用户数据报协议,一种面向无连接,且只进行数据包发送,不进行确认的协议。
Java中进行UDP数据交互基本思路:
- 设置本主机发送数据包的端口和ip。类似于建立一个站点,用于接收和发送数据包。实际上,数据包的接收端主机地址是封装在数据包之中,本地主机设置的端口只需将数据包发送或者接收即可;
- 获取需要发送的数据包用户IP。相当于获取用户的地址信息,从而获知该将数据包发往何处。
- 接收端接收发送的数据包,并对数据包进行解析。接收端在设定的端口号接收数据包,接收之后可解析数据包。
理解:UDP数据包交互类似于收取快递一般,首先建立快递站,再将需要收取和发送的快递放到快递站,由此在交给指定用户。
相应方法:
UDP编程主要依赖于以下类:
- DatagramSocket类:
作用:在本地主机设置端口,用于收发数据包,若无参数时,随机分配端口;可传入参数指定端口号。
相关方法:
Void Send(DatagramPacket val):用于发送数据包;
Void receive(DatagramPacket val):用于监听是否有数据包发送到本主机,若有则用val存储接收到的数据包。在其监听之时,会一直堵塞进程,直到有相应数据包传入(即不会执行该语句之后的代码块,直到有数据包传入)。可设置等待时间,超出该时间则结束程序。
- DatagramPacket类。
作用:用来构造数据包对象,其中包含要发送的数据包和要接收的数据包。
若是发送数据包,需要包含发送的字节数组信息,以及要将多大的数据包进行发送,同时还要拥有接收方的ip地址和端口号。
若是接收数据包,需要包含用多大的字节数组接收数据包,同时要接收多大的数据包。
若是解析信息,需要注意传回数据包中数据的长度。(缓冲区的长度不一定等于传回信息的长度,故需要以传回的信息长度为读取的大小。)
- InetAddress类。
作用:获取需要的主机地址。
UDP简易信息交互实例:
Server端代码:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.util.Scanner;
public class UDPServer {
public static final int FIL_MAX=1024;
public static final int PORT=8080;
public static final int TIMES=8000;
public DatagramSocket server;
public DatagramPacket packet;
public InetAddress address;
public InetAddress reciveaddress;
public int moPort;
public int reviceport;
public boolean marks;
public Scanner in;
//初始化信息方法
public void init() {
try {
//创建标准I/O流
in=new Scanner(System.in);
//创建服务器端口
server=new DatagramSocket(PORT);
//设置服务器拥塞时间
// server.setSoTimeout(TIMES);
//设置默认的inetaddress对象
address=InetAddress.getLocalHost();
//设置默认端口
moPort=9000;
//设置接收端口默认值
reviceport=-1;
//设置信息接收数据包
packet=new DatagramPacket(new byte[FIL_MAX],FIL_MAX);
marks=true;
System.out.println("初始化信息成功!");
} catch (Exception e) {
System.out.println("初始化信息失败!");
}
}
//服务器运行方法
public void ServerRun() {
try {
while(marks) {
System.out.println("server等待接收信息....");
//接收信息
server.receive(packet);
if(packet.getPort()!=0)
{
acceptMessage();
askInfo();
}
}
System.out.println("程序运行结束!");
} catch (Exception e) {
System.out.println("运行程序失败!");
}
}
//服务器接收方法
public void acceptMessage() {
//获取发送端主机地址信息
reciveaddress=packet.getAddress();
//获取发送端端口
reviceport=packet.getPort();
//获取发送的信息
String message=new String(packet.getData(),0,packet.getLength());
//获取发送端主机名
String addressname=reciveaddress.getHostName();
//输出信息
System.out.println("接收到来自用户"+addressname+"的信息:"+message);
}
//服务器发送信息方法
public void sendMessage() {
System.out.println("请选择要发送的对象:1默认对象 2上一次接收用户的对象");
int user=in.nextInt();
InetAddress sendaddress=address;
int ports=moPort;
if(user==2) {
if(reviceport==-1) {
System.out.println("尚未接收到信息!");
}
else {
sendaddress=address;
ports=reviceport;
}
}
System.out.println("请输入要发送的信息:");
in.nextLine();
String message=in.nextLine();
byte[] info=message.getBytes();
DatagramPacket packets=new DatagramPacket(info,info.length,sendaddress,ports);
try {
server.send(packets);
System.out.println("信息发送成功!");
} catch (Exception e) {
// TODO: handle exception
System.out.println("信息发送失败!");
}
}
public void askInfo() {
System.out.println("是否发送信息(over退出程序):Y/N");
String choic=in.next();
if(choic.equals("Y")) {
sendMessage();
}
else if(choic.equals("over")) {
server.close();
marks=false;
}
}
public static void main(String[] args) {
//创建测试对象
UDPServer test=new UDPServer();
test.init();
test.ServerRun();
}
}
Client端代码:
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;
public class UDPClient {
public static final int FIL_MAX=1024;
public static final int PORT=9000;
public static final int TIMES=3000;
public DatagramSocket client;
public DatagramPacket packet;
public InetAddress address;
public InetAddress reciveaddress;
public int moPort;
public int reviceport;
public Scanner in;
public boolean marks;
//初始化信息方法
public void init() {
try {
//创建标准I/O流
in=new Scanner(System.in);
//创建服务器端口
client=new DatagramSocket(PORT);
//设置服务器拥塞时间
// client.setSoTimeout(TIMES);
//设置默认的inetaddress对象
address=InetAddress.getLocalHost();
//设置默认端口
moPort=8080;
//设置接收端口默认值
reviceport=-1;
//设置信息接收数据包
packet=new DatagramPacket(new byte[FIL_MAX],FIL_MAX);
marks=true;
System.out.println("初始化信息成功!");
} catch (Exception e) {
System.out.println("初始化信息失败!");
}
}
//服务器运行方法
public void ClientRun() {
try {
while(marks) {
System.out.println("client等待接收信息....");
//接收信息
client.receive(packet);
if(packet.getPort()!=0) {
acceptMessage();
askInfo();
}
}
System.out.println("程序运行结束!");
} catch (Exception e) {
System.out.println("运行程序失败!");
}
}
//服务器接收方法
public void acceptMessage() {
//获取发送端主机地址信息
reciveaddress=packet.getAddress();
//获取发送端端口
reviceport=packet.getPort();
//获取发送的信息
String message=new String(packet.getData(),0,packet.getLength());
//获取发送端主机名
String addressname=reciveaddress.getHostName();
//输出信息
System.out.println("接收到来自用户"+addressname+"的信息:"+message);
}
//服务器发送信息方法
public void sendMessage() {
System.out.println("请选择要发送的对象:1默认对象 2上一次接收用户的对象");
int user=in.nextInt();
InetAddress sendaddress=address;
int ports=moPort;
if(user==2) {
if(reviceport==-1) {
System.out.println("尚未接收到信息!");
}
else {
sendaddress=address;
ports=reviceport;
}
}
System.out.println("请输入要发送的信息:");
in.nextLine();
String message=in.nextLine();
byte[] info=message.getBytes();
DatagramPacket packets=new DatagramPacket(info,info.length,sendaddress,ports);
try {
client.send(packets);
System.out.println("信息发送成功!");
} catch (Exception e) {
// TODO: handle exception
System.out.println("信息发送失败!");
}
}
//问讯信息控制
public void askInfo() {
System.out.println("是否发送信息(over退出程序):Y/N");
String choic=in.next();
if(choic.equals("Y")) {
sendMessage();
}
else if(choic.equals("over")) {
client.close();
marks=false;
}
}
public static void main(String[] args) {
//创建测试对象
UDPClient test=new UDPClient();
test.init();
test.askInfo();
test.ClientRun();
}
}
TCP交互
特点:tcp协议即传输控制协议,是一种面向连接的,可靠的具有安全性的通信协议。
Tcp协议分为服务器和客户端两部分,每次通信都需要服务器端先启动。
实现基本流程:
服务器端:
设置监听端口:设置一个监听端口,用于接收请求连接通信的客户端数据对象,彼此之间建立联系;
创建输入流:用来与客户端的输出流进行连接,实现数据读取;
创建输出流:用来与客户端的输入流进行连接,实现数据传输。
客户端:
设置socket对象,其中封装了本地的主机地址,欲要进行通信的服务器主机地址以及接收的端口号和数据等。
与服务器端相同,创建输入输出流。
主要的类:
ServerSocket类:用来创建服务器端的监听窗口。
Socket类:用来设置客户端和服务器的数据对象。
DataInputStream类:用来连接服务器和客户端的输入输出流。
DataOutputStream类:用来连接服务其和客户端的输出输入流。
注意实现:
ServerSocket类的Accept方法,用于监听是否有客户端连接,若一直未收到连接请求,将会始终处于阻塞状态,datainputstream中的read方法也会处于阻塞状态。因此若想实现服务器和客户端循环通信,需要将服务器的监听方法写在循环体外。
TCP实例代码:
服务器端:
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class SocketServer {
private ServerSocket server;
private final int PORT=8080;
private Socket client;
private DataOutputStream out;
private DataInputStream in;
private Scanner input;
private void init() {
try {
//创建服务器监听端口
server=new ServerSocket(PORT);
//创建I/O输入输出流
input=new Scanner(System.in);
System.out.println("初始化信息成功!");
} catch (Exception e) {
// TODO: handle exception
System.out.println("初始化信息失败!");
}
}
public void sendMessage() {
try {
//连接客户端的输入流
out=new DataOutputStream(client.getOutputStream());
input.nextLine();
String message=input.nextLine();
out.writeUTF(message);
System.out.println("发送成功!");
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("发送信息失败!");
}
}
public void acceptMessage() {
try {
//连接客户端的输出流
in=new DataInputStream(client.getInputStream());
String message=in.readUTF();
System.out.println("接收到来自"+client.getInetAddress().getHostName()+"的信息:"+message);
System.out.println("请输入回信内容:");
sendMessage();
} catch (Exception e) {
System.out.println("读取信息失败!");
}
}
public void ServerRun() {
try {
System.out.println("Server等待接收信息...");
client=server.accept();
while(true) {
acceptMessage();
System.out.println("是否退出程序?(y/n)");
String index=input.next();
if(index.equals("y")) {
stopServer();
System.out.println("程序已关闭!");
break;
}
System.out.println("Server等待接收信息...");
}
} catch (Exception e) {
System.out.println("程序运行失败!");
}
}
public void stopServer() {
try {
in.close();
out.close();
server.close();
input.close();
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("程序关闭失败!");
}
}
public static void main(String[] args) {
SocketServer test=new SocketServer();
test.init();
test.ServerRun();
}
}
客户端代码:
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
public class SocketClient {
private final int PORT=9000;
private final int MOPORT=8080;
private InetAddress address;
private Socket client;
private DataInputStream in;
private DataOutputStream out;
private Scanner input;
private boolean marks=false;
public void init() {
try {
address=InetAddress.getLocalHost();
client=new Socket(address, MOPORT);
in=new DataInputStream(client.getInputStream());
out=new DataOutputStream(client.getOutputStream());
input=new Scanner(System.in);
System.out.println("信息初始化成功!");
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
System.out.println("信息初始化失败!");
System.out.println(e.getMessage());
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("信息初始化失败!");
System.out.println(e.getMessage());
}
}
public void sendMessage() {
try {
System.out.println("请输入要发送的内容:");
input.nextLine();
String message=input.nextLine();
out.writeUTF(message);
System.out.println("信息已发送!");
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("信息写入失败!");
}
}
public void acceptMessage() {
try {
String mesage=in.readUTF();
System.out.println("收到来自"+client.getInetAddress().getHostName()+"的信息:"+mesage);
sendMessage();
} catch (Exception e) {
System.out.println("获取信息失败!");
System.out.println(e.getMessage());
}
}
public void stopClient() {
try {
in.close();
out.close();
input.close();
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("程序关闭失败!");
}
}
public void ClientRun() throws InterruptedException {
while(true) {
System.out.println("client....");
System.out.println("是否查看信息?y/n (over退出程序)");
String indexs=input.next();
if(indexs.equals("y")) {
if(marks) {
acceptMessage();
}
else {
System.out.println("未接收到信息,请发送信息!");
marks=true;
sendMessage();
}
}
else if(indexs.equals("over")) {
stopClient();
System.out.println("退出程序成功!");
break;
}
}
}
public static void main(String[] args) {
SocketClient test=new SocketClient();
test.init();
try {
test.ClientRun();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
System.out.println(e.getMessage());
}
}
}
URL学习
URL:资源定位符,即网络地址。
URL结构:protocol://host:port/path?query#fragment
protocol(协议)可以是 HTTP、HTTPS、FTP 和 File,host为主机名,port 为端口号,path为文件路径及文件名。
实例解析如下:
URL:http://www.baidu.com/index.html?language=cn#j2se
URL 解析:
协议为(protocol):http
主机为(host:port):www.baidu.com
端口号为(port): 80 ,以上URL实例并未指定端口,因为 HTTP 协议默认的端口号为 80。
文件路径为(path):/index.html
请求参数(query):language=cn
定位位置(fragment):j2se,定位到网页中 id 属性为 j2se 的 HTML 元素位置 。
URL有四种构造方法:
1.public URL(String protocol, String host, int port, String file) throws MalformedURLException.
通过给定的协议名称、主机号、端口号以及文件名称创建url对象。
2.public URL(String protocol, String host, String file) throws MalformedURLException。
此处未指明端口号,采用默认端口号:80
3.public URL(String url) throws MalformedURLException
通过给定的URL字符串创建URL.
4.public URL(URL context, String url) throws MalformedURLException
使用基地址和相对URL创建
注意:
若要获取URL对象的链接对象,可使用openConnection方法。
若协议为http,该方法返回 HttpURLConnection 对象
若协议为JAR 文件,该方法将返回 JarURLConnection 对象
...
针对不同的协议返回不同的URLConnect对象。
在得到的网页信息输出若有乱码,可通过如下方式解决:
BufferedReader input=new BufferedReader(new InputStreamReader(in,"utf-8"));
其中in是URLConnect返回的输入流对象(inputStream)。
其基本方法演示实例如下:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
public class URLTest{
public static void AnalyseWeb(URL webl) {
System.out.println("未指明路径和文件名,输出URL信息如下:");
System.out.println("解析对象:"+webl.toString());
System.out.println("验证信息:"+webl.getAuthority());
System.out.println("URL协议:"+webl.getProtocol());
System.out.println("URL主机名:"+webl.getHost());
System.out.println("URL端口号:"+webl.getPort());
System.out.println("URL默认端口号:"+webl.getDefaultPort());
System.out.println("URL文件名部分:"+webl.getFile());
System.out.println("URL路径部分:"+webl.getPath());
System.out.println("URL查询部分:"+webl.getQuery());
System.out.println("获取引用:"+webl.getRef());
System.out.println("连接url指定的网址对象...");
ConnectWeb(webl);
}
public static void ConnectWeb(URL webc) {
try {
URLConnection result=webc.openConnection();
System.out.println("输出"+webc.toString()+"的URLConnect对象基本信息:");
System.out.println("检索链接内容:"+result.getContent());
System.out.println("返回头部 content-encoding 字段值:"+result.getContentEncoding());
System.out.println("返回头部 content-length字段值:"+result.getContentLength());
System.out.println("返回头部 content-type 字段值:"+result.getContentType());
System.out.println("返回头部 last-modified 字段值:"+result.getLastModified());
System.out.println("返回头部 expires 字段值:"+result.getExpiration());
System.out.println("返回对象的 ifModifiedSince 字段值:"+result.getIfModifiedSince());
System.out.println("返回 URLConnection 对象连接的URL:"+result.getURL());
System.out.println("URLConnect对象的相关操作....");
OperateURL(result);
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("获取URLConnections对象失败!");
}
}
public static void OperateURL(URLConnection webo) {
System.out.println("使用"+webo.getURL()+"的URLconnect对象进行资源读入与读出");
try {
//获取webo的输入流
InputStream in=webo.getInputStream();
BufferedReader input=new BufferedReader(new InputStreamReader(in,"utf-8"));
char[] message=new char[512];
int len=0;
System.out.println("*******************输出读取到的信息如下*********************");
while((len=input.read(message))!=-1) {
System.out.println(String.valueOf(message));
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) {
try {
//创建URL对象
URL test=new URL("https://www.baidu.com");
AnalyseWeb(test);
} catch (Exception e) {
// TODO Auto-generated catch block
System.out.println(e.getMessage());
}
}
}
以上代码仅供参考,健壮性和正确性未充分验证。