1.1 概述
网络编程从大的方面说就是对信息的发送到接收,中间传输为物理线路的作用。
网络编程最主要的工作就是在发送端把信息通过规定好的协议进行组装包,在接收端按照规定好的协议把包进行解析,从而提取出对应的信息,达到通信的目的。中间最主要的就是数据包的组装,数据包的过滤,数据包的捕获,数据包的分析,当然最后再做一些处理,代码、开发工具、数据库、服务器架设和网页设计这5部分你都要接触。 ---------来源于《百度百科》
计算机网络:
计算机网络是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。
网络编程的目的:
天线电台。。。传播交流信息,数据交换。通信
如何达到这个效果:
- 准确定位到网络上的一台主机,需要一个IP地址,如:192.168.16.124
- 准确定位到这个计算机上的某个资源,需要一个端口port,如:8080
- 找到这个主机后,怎么传输数据?
javaweb: 网页编程 B/S
网络编程:TCP/IP C/S
1.2 网络通信的要素
如何实现网络的通信?
通信双方地址:
- ip
- 端口号
- 192.168.16.124 : 5900
规则:网络通信的协议
TCP/IP 参考模型
小结:
- 网络编程中有两个主要的问题
- 如何准确的定位到网络上的一台或多台主机
- 找到主机之后如何进行通信
- 网络编程中的要素
- IP和端口号 IP.
- 网络通信协议 UDP,TCP
- 万物皆对象
1.3 IP
ip地址:InetAddress
-
唯一定位一台网络上计算机
-
127.0.0.1 :本机 localhost
-
ip地址的分类
-
ipv4/ipv6
-
IPV4 127.0.0.1 , 长度为 32 位(4 个字节)。地址由网络和主机部分组成,这取决于地址类。根据地址的前几位,可定义各种地址类:A、B、C、D 或 E。IPv4 地址的总数为 4 294 967 296。
IPv4 地址的文本格式为 nnn.nnn.nnn.nnn,其中 0<=nnn<=255,而每个 n 都是十进制数。可省略前导零。最大打印字符数为 15 个,不计掩码。 -
IPV6 长度为 128 位(16 个字节)。基本体系结构的网络数字为 64 位,主机数字为 64 位。通常,IPv6 地址(或其部分)的主机部分将派生自 MAC 地址或其他接口标识。
根据子网前缀,IPv6 的体系结构比 IPv4 的体系结构更复杂。IPv6 地址的数目比 IPv4 地址的数目大 1028(79 228 162 514 264 337 593 543 950 336)倍。IPv6 地址的文本格式为 xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx,其中每个 x 都是十六进制数,表示 4 位。可省略前导零。可在地址的文本格式中使用一次双冒号(::),用于指定任意数目的 0 位。例如,::ffff:10.120.78.40 表示 IPv4 映射的 IPv6 地址。
-
-
公网(互联网)-私网(局域网)
- ABCDE类地址
- 192.168.xx.xx 专门给组织内部使用的
-
-
域名:记忆IP问题!
- www.vip.com
package zhang.lesson01;
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
* @ClassName TestInetAddress
* @Description TODO 测试IP
* @Author Administrator
* @Date 2021/3/5 12:37
* @Version 1.0
**/
public class TestInetAddress {
public static void main(String[] args) {
try {
//查询本机地址
InetAddress inetAddress1 = InetAddress.getByName("127.0.0.1");
System.out.println(inetAddress1);
InetAddress inetAddress3 = InetAddress.getByName("localhost");
System.out.println(inetAddress3);
InetAddress inetAddress4 = InetAddress.getLocalHost();
System.out.println(inetAddress4);
//查询网站ip地址
InetAddress inetAddress2 = InetAddress.getByName("www.baidu.com");
System.out.println(inetAddress2);
//常用方法
// System.out.println(inetAddress2.getAddress());
System.out.println(inetAddress2.getCanonicalHostName());//Canonical 规范的m
System.out.println(inetAddress2.getHostAddress()); //ip
System.out.println(inetAddress2.getHostName());//域名,或者自己电脑的名字
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
1.4 端口
端口表示计算机上的一个程序的进程;
-
不同的进程有不同的端口号,用来区分软件。
-
被规定0~65525
-
TCP,UDP:65535*2 tcp:80 ,udp:80 ,单个协议下,端口号不能冲突
-
端口分类
-
公有端口 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 "5900" #查看指定的端口 tasklist|findstr "8696" #查看指定端口的进程 任务管理器 快捷键 Crtl + shift +Esc
-
package zhang.lesson01;
import java.net.InetSocketAddress;
/**
* @ClassName TestInetSocketAddress
* @Description TODO
* @Author Administrator
* @Date 2021/3/5 13:43
* @Version 1.0
**/
public class TestInetSocketAddress {
public static void main(String[] args) {
InetSocketAddress socketAddress = new InetSocketAddress("127.0.0.1",8080);
InetSocketAddress socketAddress2 = new InetSocketAddress("localhost",8080);
System.out.println(socketAddress);
System.out.println(socketAddress2);
System.out.println(socketAddress.getAddress());
System.out.println(socketAddress.getHostName());//IP地址
System.out.println(socketAddress.getPort());//端口
}
}
1.5 通信协议
协议:约定,就好比我们现在说的是普通话
网络通信协议: 速率,传输码率,代码结构,传输控制。。。
TCP/IP协议簇:实际上是一组协议
重要:
- TCP:用户传输协议
- UDP:用户数据报协议
出名的协议:
- TCP:
- IP:网络互联协议
TCP UDP 对比
TCP:打电话
- 连接,稳定
- 三次握手,四次挥手
最少需要三次,保证稳定连接!
A:你瞅啥?
B:瞅你乍地?
A:干一场
A:我要断开了
B:我知道你要断开了
B:你真的真的要断开了码?
A:我真的要走了
- 客户端、服务端
- 传输完成,释放连接、效率低
UDP:发短信
- 不连接,不稳定
- 客户端、服务端:没有明确的界限
- 不管有没有准备号,都可以发给你
- 导弹
- DDOS:洪水攻击!(饱和攻击)
1.6 TCP
客户端
-
连接服务器 Socket
-
发送消息
package zhang.lesson02; import java.io.IOException; import java.io.OutputStream; import java.net.InetAddress; import java.net.Socket; import java.net.UnknownHostException; /** * @ClassName TcpClientD恶魔 * @Description TODO * @Author Administrator * @Date 2021/3/5 14:16 * @Version 1.0 **/ 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"); int port = 9999; //2. 创建一个socket连接 socket =new Socket(serverIP,port); // 发送消息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(); } } } } }
服务端
-
建立服务的端口 ServerSocket
-
等待用户的连接 accept
-
接受用的消息
package zhang.lesson02;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
* @ClassName TcpServerDemo01
* @Description TODO
* @Author Administrator
* @Date 2021/3/5 14:17
* @Version 1.0
**/
public class TcpServerDemo01 {
public static void main(String[] args) {
ServerSocket serverSocket = null;
Socket socket = null;
InputStream is = null;
ByteArrayOutputStream baos = null;
try {
//1.我得有个地址
serverSocket = new ServerSocket(9999);
while (true){
//2.等待客户端连接过来
socket = serverSocket.accept();
//3.读取客户端的消息
is = socket.getInputStream();
/*
byte[] buffer = new byte[1024];
int len;
while((len=is.read(buffer)) != -1)){
String msg = new String(buffer,0,len);
System.out.println(msg);
}
*/
//为了避免出现乱码的情况,我们要套上一层管道流
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());
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
baos.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
文件上传
客户端
package zhang.lesson02;
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
/**
* @ClassName TestClientDemo02
* @Description TODO
* @Author Administrator
* @Date 2021/3/5 15:28
* @Version 1.0
**/
public class TestClientDemo02 {
public static void main(String[] args) throws IOException {
//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("baidu.png"));
//4. 写出文件
byte[] buffer = new byte[1024];
int len;
while ((len = fis.read(buffer) )!= -1){
os.write(buffer,0,len);
}
//通知服务器,我已经结束了
socket.shutdownOutput();//我已经传输完了
//确定服务器接受完毕,才能够断开连接
InputStream inputStream = socket.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer2 = new byte[1024];
int len2;
while ((len2 = inputStream.read(buffer2)) != -1){
baos.write(buffer2,0,len2);
}
System.out.println(baos.toString());
//5.关闭资源
fis.close();
os.close();
socket.close();
}
}
服务端
package zhang.lesson02;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
/**
* @ClassName TestServerDemo02
* @Description TODO
* @Author Administrator
* @Date 2021/3/5 15:38
* @Version 1.0
**/
public class TestServerDemo02 {
public static void main(String[] args) throws IOException {
//1.创建服务
ServerSocket serverSocket = new ServerSocket(9000);
//2. 监听客户端连接
Socket socket = serverSocket.accept();//阻塞是监听,会一直等待客户端连接
//3.获取输入流
InputStream is= socket.getInputStream();
//4.文件输出
FileOutputStream fos = new FileOutputStream(new File("receive.png"));
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. 关闭资源
fos.close();
is.close();
socket.close();
serverSocket.close();
}
}
Tomcat
服务端
- 自定义 S
- Tomcat 服务器S: Java后台开发!
客户端
- 自定义C
- 浏览器B
Tomcat 下载、安装、配置图文教程
参考博文:https://blog.youkuaiyun.com/u010282984/article/details/80884810
1.7 UDP
发短信:不用连接,需要知道对方的地址!
发送端
package zhang.lesson03;
import java.io.IOException;
import java.net.*;
/**
* @ClassName UdpClientDemo01
* @Description TODO
* @Author Administrator
* @Date 2021/3/5 16:30
* @Version 1.0
**/
//不需要连接服务器
public class UdpClientDemo01 {
public static void main(String[] args) throws IOException {
//1. 建立一个Socket
DatagramSocket socket = new DatagramSocket();
//2. 建个包
String msg = "你好啊,服务器!";
InetAddress localhost = InetAddress.getByName("localhost");
int port = 9090;
//数据,数据的长度起始,要发送给谁
DatagramPacket packet = new DatagramPacket(msg.getBytes(),0,msg.getBytes().length,localhost,port);
//3. 发送包
socket.send(packet);
//4. 关闭流
socket.close();
}
}
接受端
package zhang.lesson03;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
/**
* @ClassName UdpServerDemo01
* @Description TODO
* @Author Administrator
* @Date 2021/3/5 16:45
* @Version 1.0
**/
//还是要等待客户端的连接!
public class UdpServerDemo01 {
public static void main(String[] args) throws IOException {
//开发端口
DatagramSocket socket = new DatagramSocket(9090);
//接受数据包
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();
}
}
咨询案例(双线程)
package zhang.chat;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
/**
* @ClassName TalkSend
* @Description TODO
* @Author Administrator
* @Date 2021/3/5 17:50
* @Version 1.0
**/
public class TalkSend implements Runnable{
DatagramSocket socket = null;
BufferedReader reader = null;
private int fromPort;
private String toIP;
private int toPort;
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 (Exception e){
e.printStackTrace();
}
}
@Override
public void run() {
while (true){
String data = null;
try {
data = reader.readLine();
byte[] datas = data.getBytes();
DatagramPacket packet = new DatagramPacket(datas,0,datas.length,new InetSocketAddress(this.toIP,this.toPort));
socket.send(packet);
if (data.equals("bye")){
break;
}
} catch (IOException e) {
e.printStackTrace();
}
}
socket.close();
}
}
package zhang.chat;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
/**
* @ClassName TalkReceive
* @Description TODO
* @Author Administrator
* @Date 2021/3/5 18:03
* @Version 1.0
**/
public class TalkReceive implements Runnable {
DatagramSocket socket = null;
private int port;
private String msgFrom;
public TalkReceive( int port, String msgFrom) {
this.msgFrom= msgFrom;
this.port = port;
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());
/*
String receiveData = new String(data,0,data.length);
会将整个data当成字符串.会有很多空格的
*/
System.out.println(msgFrom+":"+receiveData);
if (receiveData.equals("bye")){
break;
}
} catch (IOException e) {
e.printStackTrace();
}
}
socket.close();
}
}
package zhang.chat;
/**
* @ClassName TalkStudent
* @Description TODO
* @Author Administrator
* @Date 2021/3/5 18:18
* @Version 1.0
**/
public class TalkStudent {
public static void main(String[] args) {
//开启两个线程
new Thread(new TalkSend(7777,"localhost",9991)).start();
new Thread(new TalkReceive(8881,"老师")).start();
}
}
package zhang.chat;
/**
* @ClassName TalkTeacher
* @Description TODO
* @Author Administrator
* @Date 2021/3/5 18:24
* @Version 1.0
**/
public class TalkTeacher {
public static void main(String[] args) {
new Thread(new TalkSend(5555,"localhost",8881)).start();
new Thread(new TalkReceive(9991,"学生")).start();
}
}
1.8 URL
https://www.baidu.com/
统一资源定位符:定位资源的,定位互联网上的某一个资源
DNS域名解释 www.baidu.com xxx.x…xx…xx
协议://ip地址:端口/项目名/资源
package zhang.lesson04;
import java.net.MalformedURLException;
import java.net.URL;
/**
* @ClassName URLDemo01
* @Description TODO
* @Author Administrator
* @Date 2021/3/5 19:18
* @Version 1.0
**/
public class URLDemo01 {
public static void main(String[] args) throws MalformedURLException {
URL url = new URL("http://localhost:8080/helloworld/index.jsp?username=kuangshen&password=123");
System.out.println(url.getProtocol());//协议
System.out.println(url.getHost());//主机IP
System.out.println(url.getPort());//端口
System.out.println(url.getPath());//文件
System.out.println(url.getFile());//全路径
System.out.println(url.getQuery());//参数
}
}
package zhang.lesson04;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
/**
* @ClassName UrlDown
* @Description TODO
* @Author Administrator
* @Date 2021/3/6 11:05
* @Version 1.0
**/
public class UrlDown {
public static void main(String[] args) throws IOException {
//1.下载地址
URL url = new URL("http://localhost:8080/xiaozhang/SecurityFile.txt");
//2.连接到这个资源 HTTP
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
InputStream inputStream = urlConnection.getInputStream();
FileOutputStream fos =new FileOutputStream("SecurityFile.txt");
byte[] buffer = new byte[1024];
int len;
while ((len=inputStream.read(buffer)) != -1){
fos.write(buffer,0,len);//写出数据
}
fos.close();
inputStream.close();
urlConnection.disconnect();//断开连接
}
}