Java网络编程学习
1、概述
计算机网络:
实现网络传输的三个要素:
- 使用IP地址(准确地定位网络上一台或多台主机)
- 使用端口号(定位主机上的特定的应用)
- 规范网络通信协议(可靠、高效地进行数据传输)
网络编程的目的:
无线电台。。。传播交流信息、数据交换、通信
2、通信的三要素
2.1、IP地址
作用:
IP地址用来给网络中的一台计算机设备做唯一的编号。
本地回路地址:127.0.0.1
IP地址分类:
公网地址( 万维网使用)和 私有地址( 局域网使用。以192.168开头)。
IPv4:是一个32位的二进制数,通常被分为4个字节,表示成
a.b.c.d
的形式,以点分十进制
表示,例如192.168.65.100
。其中a、b、c、d都是0~255之间的十进制整数。
IPV6:占用16个字节 fe80::4bb0:5fbc:627:3888%14 128位,8个无符号整数域名
2.2、端口号
可以唯一标识设备中的进程(应用程序)。
不同的进程分配不同的端口号
范围:0~65535
端口分类:
公有端口 0~1023
- HTTP:80
- HTTPS:443
- FTP:21
- Telent:23
程序注册端口:1024~49151,分配用户或者程序
- Tomcat:8080
- MySQL:3306
- Oracle:1521
动态、私有:49152~65535
netstat -ano #查看所有的端口 netstat -ano|findstr "xxx" #查看指定的端口 tasklist|findstr "xxx" #查看指定端口的进程 Ctrl+Shift+ESC #快捷打开控制面板
2.3、网络通信协议
TCP/IP参考模型和OSI参考模型:
3、网络编程中所涉及到的类
3.1、IP
ip地址:InetAddress
public class IPDemo {
public static void main(String[] args) {
try {
//查询本机地址
InetAddress address = InetAddress.getByName("127.0.0.1");
System.out.println(address);
InetAddress address2 = InetAddress.getByName("localhost");
System.out.println(address2);
InetAddress host = InetAddress.getLocalHost();
System.out.println(host);
//查询网站ip地址
InetAddress address1 = InetAddress.getByName("www.baidu.com");
System.out.println(address1);
//常用方法
System.out.println(address.getAddress());
System.out.println(address.getHostName());
System.out.println(address.getHostAddress());
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
3.2、端口
配置本地映射地址:
C:\Windows\System32\drivers\etc\hosts
Socket类
public class PortDemo {
public static void main(String[] args) {
InetSocketAddress socketAddress = new InetSocketAddress("127.0.0.1", 8080);
System.out.println(socketAddress);
System.out.println(socketAddress.getPort());//获取端口
System.out.println(socketAddress.getHostName());//获取地址
}
}
3.3、通信协议
3.3.1、TCP和UDP介绍
网络通信协议: 速率,传输码率,代码结构,传输控制。。。。。。
TCP/IP协议簇:实际上是一组协议
TCP:
用户传输协议
TCP协议进行通信的两个应用进程:客户端、服务端。
使用TCP协议前,须先建立TCP连接,形成基于字节流的传输数据通道
传输前,采用“三次握手”方式,点对点通信,是可靠的
最少需要三次,保证稳定连接
TCP协议使用重发机制,当一个通信实体发送一个消息给另一个通信实体后,需要收到另一个通信实体确认信息,如果没有收到另一个通信实体确认信息,则会再次重复刚才发送的消息。
在连接中可进行大数据量的传输
传输完毕,需释放已建立的连接,效率低
UDP:
用户数据报协议
UDP协议进行通信的两个应用进程:发送端、接收端。
将数据、源、目的封装成数据包(传输的基本单位),不需要建立连接
发送方不管对方是否准备好,接收方收到也不确认,不能保证数据的完整性,故是不可靠的
每个数据报的大小限制在64K内
发送数据结束时无需释放资源,开销小,通信效率高
适用场景:音频、视频和普通数据的传输。例如视频会议
3.3.2、TCP代码实现
-
TCP客户端:
- 连接服务器Socket
- 发送消息
public class TCPClientDemo01 {
public static void main(String[] args) {
Socket socket=null;
OutputStream os =null;
try {
//1.获取服务器的地址
InetAddress serverIP = InetAddress.getByName("127.0.0.1");
//2.设置端口号,和服务器的端口号相同
int port=9999;
//3.创建一个socket连接
socket = new Socket(serverIP, port);
//4.发送消息 IO流
os = socket.getOutputStream();
os.write("欢迎,来到Java世界!".getBytes());
} catch (Exception e) {
e.printStackTrace();
}finally {
if (os!=null){
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket!=null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
-
TCP服务器:
- 建立服务端的端口 serverSocket
- 等待用户的连接 accept
- 接收用户的消息
public class TCPServerDemo01 {
public static void main(String[] args) {
ServerSocket serverSocket = null;
Socket accept = null;
InputStream is = null;
ByteArrayOutputStream baos = null;
try {
//1.设置服务器的地址(包括端口)
serverSocket = new ServerSocket(9999);
while (true){
//2.等待客户端连接
accept = serverSocket.accept();
//3.读取客户端的消息
is = accept.getInputStream();
//管道流
baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
while ((len= is.read(buffer))!=-1){
baos.write(buffer,0,len);
}
System.out.println(baos.toString());
}
// byte[] buffer=new byte[1024];
// int len;
// while ((len= is.read(buffer))!=-1){
// String s = new String(buffer, 0, len);
// System.out.println(s);
// }
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭流
if (baos!=null){
try {
baos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (is!=null){
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (accept!=null){
try {
accept.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (serverSocket!=null){
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
- TCP实现文件上传
//客户端代码
/*
注意:这里的异常处理建议使用try-catch-finally方式,图片的路径是在project下,如果放在其他路径,以下代码会报错
*/
public class TCPClientDemo02 {
public static void main(String[] args) throws Exception {
//1,创建一个Socket连接
Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 9000);
//2.创建一个输出流
OutputStream os = socket.getOutputStream();
//3.读取文件
FileInputStream fis = new FileInputStream(new File("picture.jpg"));
//4.写出文件
byte[] buffer = new byte[1024];
int len;
while ((len= fis.read(buffer))!=-1){
os.write(buffer,0,len);
}
//通知服务器,我已经结束了
socket.shutdownOutput();//我已经传输完了
//确定服务器接收完毕,才能断开连接
InputStream is = socket.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer1 = new byte[1024];
int len1;
while ((len1=is.read(buffer1))!=-1){
baos.write(buffer1,0,len1);
}
System.out.println(baos.toString());
//5.关闭资源
baos.close();
is.close();
fis.close();
os.close();
socket.close();
}
}
//服务器端
//这里的异常处理也建议使用try-catch-finally方式处理
public class TCPServerDemo02 {
public static void main(String[] args) throws Exception{
//1.创建服务端socket
ServerSocket serverSocket = new ServerSocket(9000);
//2.监听客户端连接
Socket socket = serverSocket.accept();//阻塞式监听,会一直等待客户端连接
//3.获取输入流
InputStream is = socket.getInputStream();
//4.文件输出
FileOutputStream fos = new FileOutputStream(new File("receive.jpg"));
byte[] buffer = new byte[1024];
int len;
while ((len=is.read(buffer))!=-1){
fos.write(buffer,0,len);
}
//通知客户端我接收完毕了
OutputStream os = socket.getOutputStream();
os.write("我已经接收完毕".getBytes());
//5.关闭资源
os.close();
fos.close();
is.close();
socket.close();
serverSocket.close();
}
}
3.3.3、Tomcat
服务端
- 自定义 S
- Tomcat服务器
客户端
- 自定义 C
- 浏览器 B
Tomcat配置,自行在网上查找教程配置
打开Tomcat后(可通过F:\IDEA\Tomcat\apache-tomcat-8.5.93\bin\startup.bat
,双击打开),浏览器输入:
locahost:8080
出现Tomcat的页面
关闭Tomcat服务,上述页面就无法打开
3.3.4、UDP代码实现
-
发送消息
-
发送端
public class UDPClientDemo01 { public static void main(String[] args) throws Exception { //1.建立一个Socket DatagramSocket socket = new DatagramSocket(); //2.建个包 String msg="你好啊,服务器!"; InetAddress address = InetAddress.getByName("localhost");//发送给谁 int port=9000; DatagramPacket packet = new DatagramPacket(msg.getBytes(),0,msg.getBytes().length,address,port); //3.发送包 socket.send(packet); //4.关闭流 socket.close(); } }
-
接收端
public class UDPServerDemo01 { public static void main(String[] args) throws Exception { //开放端口 DatagramSocket socket = new DatagramSocket(9000); //接收数据包 byte[] buffer = new byte[1024]; DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);//接收 socket.receive(packet);//阻塞接收 System.out.println(packet.getAddress().getHostAddress()); System.out.println(new String(packet.getData(),0,packet.getLength())); //关闭连接 socket.close(); } }
-
UDP聊天代码实现(类似网站咨询页面)
- 实现循环发送和接收消息
//Sender public class UDPSenderDemo01 { public static void main(String[] args) throws Exception { DatagramSocket socket = new DatagramSocket(8888); //准备数据:控制台读取System.in BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); while (true){ String s = reader.readLine(); byte[] data = s.getBytes(); DatagramPacket packet = new DatagramPacket(data,0,data.length, new InetSocketAddress("localhost",6666)); socket.send(packet); if (data.equals("bye")){ break; } } socket.close(); } }
//Receiver public class UDPRecieverDemo01 { public static void main(String[] args) throws Exception { DatagramSocket socket = new DatagramSocket(6666); while (true){ //准备接收包裹 byte[] container=new byte[1024]; DatagramPacket packet = new DatagramPacket(container,0,container.length); socket.receive(packet);//阻塞式接收包裹 //断开连接 bye byte[] data=packet.getData(); // System.out.println(data.length); // System.out.println(packet.getLength()); String receiveData = new String(data,0, packet.getLength()); System.out.println(receiveData); if (receiveData.equals("bye")){ break; } } socket.close(); } }
- 在线咨询:双方都可发送和接收消息
//采用多线程进行处理 //发送消息线程 public class TalkSend implements Runnable{ DatagramSocket socket =null; BufferedReader reader=null; private int fromPort;//自己的端口号 private String toIP;//对方的ip private int toPort;//对方的端口号 public TalkSend() { } public TalkSend(DatagramSocket socket) { this.socket = socket; } public TalkSend(int fromPort, String toIP, int toPort) { this.fromPort = fromPort; this.toIP = toIP; this.toPort = toPort; try { socket= new DatagramSocket(fromPort); reader = new BufferedReader(new InputStreamReader(System.in)); } catch (SocketException e) { e.printStackTrace(); } } @Override public void run() { //准备数据:控制台读取System.in while (true){ try { String s = reader.readLine(); byte[] data = s.getBytes(); DatagramPacket packet = new DatagramPacket(data,0,data.length, new InetSocketAddress(toIP,toPort)); socket.send(packet); if (data.equals("bye")){ break; } } catch (IOException e) { e.printStackTrace(); } } socket.close(); } } //接收消息线程 public class TalkReceive implements Runnable{ DatagramSocket socket=null; private int port; private String msgFrom;//发送方 public TalkReceive(int port,String msgFrom) { this.port = port; this.msgFrom=msgFrom; try { socket=new DatagramSocket(port); } catch (SocketException e) { e.printStackTrace(); } } @Override public void run() { while (true){ try { //准备接收包裹 byte[] container=new byte[1024]; DatagramPacket packet = new DatagramPacket(container,0,container.length); socket.receive(packet);//阻塞式接收包裹 //断开连接 bye byte[] data=packet.getData(); String receiveData = new String(data,0, packet.getLength()); System.out.println(msgFrom+" :"+receiveData); if (receiveData.equals("bye")){ break; } } catch (IOException e) { e.printStackTrace(); } } socket.close(); } }
//测试代码 public class TalkStudent { public static void main(String[] args) { //开启两个线程 new Thread(new TalkSend(7777,"localhost",9999)).start(); new Thread(new TalkReceive(8888,"老师")).start(); } } ----------------------------------------------------------------------------------------------------- public class TalkTeacher { public static void main(String[] args) { new Thread(new TalkSend(5555,"localhost",8888)).start(); new Thread(new TalkReceive(9999,"学生")).start(); } }
-
4、URL
统一资源定位符:定位资源的,定位互联网上的某一个资源
DNS 域名解析
http://192.168.21.107:8080/examples/wy.jpeg?name=Tom
协议://ip地址:端口/项目名
public class URLDemo01 {
public static void main(String[] args) throws MalformedURLException {
URL url = new URL("http://localhost:8080/helloworld/index.jsp?username=gcy&password=123");
System.out.println(url.getProtocol());//获取协议名 http
System.out.println(url.getHost());//获取主机ip localhost
System.out.println(url.getPort());//获取端口号 8080
System.out.println(url.getPath());//获取文件地址 /helloworld/index.jsp
System.out.println(url.getFile());//获取文件全路径 /helloworld/index.jsp?username=gcy&password=123
System.out.println(url.getQuery());//获取查询参数 username=gcy&password=123
}
}
URL下载网络资源
-
在
F:\IDEA\Tomcat\apache-tomcat-8.5.93\webapps
文件下创建一个文件夹,在该文件夹下创建了一个txt文件,如下: -
打开Tomcat,通过网址
localhost:8080/gcy/SecurityFile.txt
,可以看到刚刚创建的txt文件的内容,如下: -
通过URL下载刚刚创建的txt文件,如下:
public class URLDemo02 { public static void main(String[] args) throws Exception{ //1.下载地址 URL url = new URL("http://localhost:8080/gcy/SecurityFile.txt"); //2.连接到该资源 HTTP HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); InputStream is = urlConnection.getInputStream(); FileOutputStream fos = new FileOutputStream("SecurityFile.txt"); byte[] buffer=new byte[1024]; int len; while ((len=is.read(buffer))!=-1){ fos.write(buffer,0,len); } fos.close(); is.close(); urlConnection.disconnect(); } }