1. 网络编程:远不止于“Hello World”
- 啥是网络?说白了,就是把各地的电脑用线连起来,共享点“秘密”。
- 为啥要网络编程?为了让数据飞起来,协议就是规则,没规矩不成方圆。
- WWW是啥?这玩意学名“全球信息网”,别被唬住,就是你每天冲浪的地方。
网络通信,离不开这俩:
- Socket:IP地址+端口号,就像你家的门牌号,别人才能找到你。
- 协议:你讲中文,我也讲中文,不然鸡同鸭讲。
协议分三块:你说啥(语义),咋说(语法),说完咋办(变换规则)。
参考模型这块,OSI太学院派,TCP/IP才是实战派,看图:

1.1 IP地址和端口号:网络世界的坐标
1.1.1 IP地址:你的网络身份证
IP地址,就是你在网络上的唯一身份证明。

IP地址这玩意儿,有几个特点:
- 32位整数,分成四段,每段0~255。别问我为啥是255,二进制8位最大值。
- 一个局域网内,IP不能重样,不然就乱套了。
- 数据传输时,IP不能变,不然就迷路了。
IP还分ABCDE五类,但常用的就是这三兄弟:
- A类:10.0.0.0~10.255.255.255,土豪专用,一般公司用不上。
- B类:172.16.0.0~172.31.255.255,中产阶级,稍微大点的公司喜欢用。
- C类:192.168.0.0~192.168.255.255,平民老百姓,小公司、家庭宽带都是它。
1.1.2 端口号:程序的小房间
端口,就像你家里的不同房间,每个房间住着不同的程序。
端口这东西,也有讲究:
- 程序和外界交流的窗口,没它就闭门造车了。
- 一台机器上,端口号不能冲突,不然程序就打架了。
-
端口号0~65535,也分三类:
- 公认端口(0~1023):大佬专用,留给那些特殊服务,别乱动。
- 注册端口(1024~49151):小弟们随便用,应用程序一般都在这儿。
- 动态/私有端口(49152~65535):土豪私用,系统动态分配,一般不用管。
1.2 通信协议:网络世界的语言
1.2.1 TCP/IP协议:可靠老大哥
TCP/IP,网络通信的基石,传输层(TCP)+网络层(IP)的组合拳。先握手,再传输,保证数据不丢包。
TCP报文长啥样?看图:

TCP报文里,这些字段很重要:
- 序号(Seq):发出去的数据包,排个号,方便对方确认。
- 确认号(Ack):收到没?收到啦!Ack就是回执。
-
标志位(Flags):URG、ACK、PSH、RST、SYN、FIN,各种指令,控制连接。
- ACK:确认号生效,必须置1。
- URG:紧急指针,插队的。
- PSH:赶紧交给应用层,别磨蹭。
- RST:连接出问题了,重来!
- SYN:发起新连接,第一次握手。
- FIN:断开连接,拜拜了您嘞。
三次握手:

- 客户端:我可以发数据给你吗?(SYN=1,Seq=X)
- 服务端:可以,我收到你的请求了。(SYN=1,ACK=1,Seq=Y,Ack=X+1)
- 客户端:好的,我开始发了。(ACK=1,Seq=X+1,Ack=Y+1)
完事,开始愉快地传输数据。

四次挥手:

- 客户端:我不玩了,要断开了。(FIN=1,Seq=U)
- 服务端:收到,我先处理一下。(ACK=1,Seq=V,Ack=U+1)
- 服务端:我也准备好了,可以断开了。(FIN=1,ACK=1,Seq=W,Ack=U+1)
- 客户端:好的,拜拜。(ACK=1,Seq=U+1,Ack=W+1)
等一会儿,确认大家都走了,才算彻底断开。
Java玩转TCP:
发送数据:
- 建个客户端Socket。
- 搞个输出流,往里写数据。
- 关门大吉,释放资源。
收数据:
- 建个服务端ServerSocket。
- 等着客户端来连接,来一个给个Socket。
- 搞个输入流,读数据,打印出来。
- 关门大吉,释放资源。
代码示例:
`import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
public class ClientDemo {
public static void main(String[] args) throws IOException, IOException {
//创建客户端的Socket对象(Socket)
Socket s=new Socket(InetAddress.getByName("192.168.0.66"),10000);
//获取输出流,写数据
OutputStream os=s.getOutputStream();
os.write("hello,tcp,我来了".getBytes());
//释放资源
s.close();
}
}
`
`import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDemo {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
//创建服务器的Socket对象(ServerSocket)
ServerSocket ss=new ServerSocket(10000);
//侦听要连接到此套接字并接受它
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);
//释放资源
s.close();
ss.close();
}
}
`
1.2.2 UDP协议:简单粗暴老铁
UDP,简单粗暴,不管你收到没,发完就完事。
TCP是可靠连接,UDP是无连接。TCP像打电话,UDP像发短信。
| TCP:传输控制协议 | UDP:用户数据报协议 |
|---|---|
| 必须建立连接,形成传输通道 | 将数据,源,目的封装成数据包,不是必须建立连接 |
| 传输前,采用“三次握手”,是可靠的 | 数据包大小是64K |
| TCP通信位于两个进程(C/S) | 因无需连接,不可靠 |
| 可以传输大量数据 | 传完数据无需释放资源,效率高 |
| 传输需要释放已建立连接,效率低 |
UDP发送数据:
- 创建发送端Socket(DatagramSocket)。
- 把数据打包。
- 发送数据。
- 关门。
UDP接收数据:
- 创建接收端Socket(DatagramSocket)。
- 创建一个数据包,准备接收数据。
- 接收数据。
- 解析数据包,打印出来。
- 关门。
代码示例:
`import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class SendDemo {
//public class DatagramSocket//用于发送和接收数据
//extends Object
//implements Closeable
public static void main(String[] args) throws IOException {
//*创建发送端的Socket对象DatagramSocket
DatagramSocket ds=new DatagramSocket();
//创建数据,并把数据打包
//DatagramPacket(byte[] buf,int length,InetAddress address,int port)
//构造一个数据包,发送长度为length的数据包到指定主机上的指定端口号
// byte[] bys="hello,udp,我来了".getBytes();
// int len=bys.length;
// InetAddress address=InetAddress.getByName("127.0.0.1");
// int port=10086;
// DatagramPacket dp=new DatagramPacket(bys,len,address,port);
byte[] bys="hello,udp,我来了".getBytes();
DatagramPacket dp=new DatagramPacket(bys,bys.length,InetAddress.getByName("127.0.0.1"),10086);
//调用DatagramSocket对象的方法发送数据
//void send(DatagramSocket p)从此套接字发送数据报包
ds.send(dp);
//***关闭发送端
ds.close();
}
}
`
`import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class ReceiveDemo {
public static void main(String[] args) throws IOException {
//1.创建接收端的Socket对象(DatagramSocket)
//DatagramSocket(int port)构造数据包套接字,并将其绑定在本地主机指定的端口上
DatagramSocket ds=new DatagramSocket(10086);
//2.创建一个数据包,用于接收数据
//DatagramPacket(byte[] buf,int length)构造一个
byte[] bys=new byte[1024];
DatagramPacket dp=new DatagramPacket(bys, bys.length);
// 3.调用DatagramSocket对象的方法用于接收数据
ds.receive(dp);
// 4.解析数据包,并把数据输出在控制台上
// byte[] getData()返回数据缓冲区
byte[] datas=dp.getData();//得到的是数据缓冲区
int len=dp.getLength();//用于获取数据长度,不使用此方法,则输出的数据后面会跟上一条空格
String dataString=new String(datas,0,len);
System.out.println("数据是:"+dataString);
// 5.关闭数据
ds.close();
}
}
`
记住:先启动服务器,再启动客户端!
1.3 HTTP和HTTPS:网页背后的秘密
- HTTP:超文本传输协议,明文传输,端口80,不安全。
- HTTPS:HTTP+SSL/TLS,加密传输,端口443,安全。
2. Java网络编程:工具箱大揭秘
Java的java.net包,就是网络编程的工具箱,里面啥都有。
URL和URLConnection:访问Web服务的利器。URLDecoder和URLEncoder:字符串和网络编码之间的翻译官。
2.1 InetAddress:网络世界的门牌号
InetAddress,就像一个网络地址的代表,有了它,才能找到目标。

常用方法:
getByName(String host):根据主机名获取InetAddress对象。getByAddress(byte[] addr):根据IP地址获取InetAddress对象。getCanonicalHostName():获取完整域名。getHostAddress():获取IP地址字符串。getHostName():获取主机名。getLocalHost():获取本机IP地址。isReachable(long timeout):测试能否连接到该IP。
代码示例:
//方法测试 //本机地址:172.23.127.177 InetAddress ip = InetAddress.getByName("172.23.127.175");//true //这个只能使用本机回环地址,很呆不建议使用 InetAddress ip2 = InetAddress.getByAddress(new byte[]{127,0,0,1});//true //是否可达 System.out.println(ip.isReachable(2000)); System.out.println(ip2.isReachable(2000)); //返回此IP的全限定域名 String canonicalHostName = ip2.getCanonicalHostName();//activate.navicat.com:这个地方是因为host文件中标注了本机回环地址的域名 System.out.println(canonicalHostName); System.out.println(InetAddress.getLocalHost());//DESKTOP-KHT7LHO/172.23.127.177
URLDecoder和URLEncoder:
encode():编码,把普通字符串变成网络编码。decode():解码,把网络编码还原成普通字符串。
代码示例:
try { String encode = URLEncoder.encode("这是一封给未来的信", "UTF-8"); String decode = URLDecoder.decode(encode, "UTF-8"); System.out.println("编码结果:"+encode+"解码结果:"+decode); //%E8%BF%99%E6%98%AF%E4%B8%80%E5%B0%81%E7%BB%99%E6%9C%AA%E6%9D%A5%E7%9A%84%E4%BF%A1 //这是一封给未来的信 } catch (UnsupportedEncodingException e) { e.printStackTrace(); }
2.2 URL和URLConnection:访问网络资源的钥匙
URL:统一资源定位符,就是你访问的每个网页的地址。
protocol://host:port/resourceName
例如:https://www.bilibili.com/video
2.2.1 URL类:URL的Java化身
URL类,就是把URL地址变成一个Java对象。
常用方法:
getFile():获取资源名。getHost():获取主机名。getPath():获取路径。getPort():获取端口号。getQuery():获取查询字符串。openConnection():建立连接,返回URLConnection对象。openStream():打开连接,返回InputStream对象,读取资源。
2.2.2 URLConnection和HttpConnection:连接网络的桥梁
URLConnection:表示程序和URL之间的连接。
HttpURLConnection:URLConnection的HTTP专用版。
步骤:
openConnection():创建URLConnection对象。- 设置参数和属性。
connect():建立连接(GET请求)。POST请求需要获取输出流发送参数。- 访问资源头字段或读取资源数据。
常用方法:
setAllowUserInteraction():设置是否允许用户交互。setDoInput():设置是否允许输入。setDoOutput():设置是否允许输出。setIfModifiedSince():设置If-Modified-Since头字段。setUseCaches():设置是否使用缓存。setRequestProperty(String key, String value):设置请求头字段。addRequesrProperty(String key, String value):增加请求头字段。getContent():获取内容。getHeaderFiled(String name):获取响应头字段。getInputStream():获取输入流。getOutputStream():获取输出流。
还有一些获取内容信息的:
getContentEncoding():获取编码。getContentLength():获取内容长度。getContentType():获取内容类型。getDate():获取日期。getExpiration():获取过期时间。getLastModified():获取最后修改时间。
代码示例:
`package com.carl.tool;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
/*
* @author :Carl_蔡先生
* @version :JDK1.8
* @description:TODO
* @date :2021/8/26 10:14
* @month_name :8月
* @week :
/
public class MultithreadDownload {
//定义下载资源的路径
private String srcPath;
//指定下载文件存放的目标路径
private String destPath;
//指定线程数
private int threadNum;
//定义下载的线程对象
private DownThread[] threads;
//指定可下载文件的总大小
private int fileSize;
public MultithreadDownload(String srcPath, String destPath, int threadNum) {
this.srcPath = srcPath;
this.destPath = destPath;
this.threadNum = threadNum;
threads=new DownThread[threadNum];
}
//下载
public void download() throws IOException {
//1.创建URL对象
URL url=new URL(srcPath);
//2.开启该URL的远程连接
HttpURLConnection conn=(HttpURLConnection) url.openConnection();
//连接时间超过五秒--超时连接--连接失败
conn.setConnectTimeout(5*1000);
//GET
conn.setRequestMethod("GET");
conn.setRequestProperty("Accept", "image/gif,image/jpeg,image/pjpeg,image/png,"
+"application/x-shockwave-flash,application/xaml+xml,"
+"application/vnd.ms-xpsdocument,application/x-ms-xbap,"
+"application/x-ms-application,application/vnd.ms-excel,"
+"application/vnd.ms-powerpoint,application/msword,*/*");
conn.setRequestProperty("Accept-Language", "zh-CN");
conn.setRequestProperty("Charset", "UTF-8");
conn.setRequestProperty("Connection", "Keep-Alive");
//获取文件大小
fileSize= conn.getContentLength();
conn.disconnect();
int currentPartSize=fileSize/threadNum+1;
//3.创建本地文件
RandomAccessFile file = new RandomAccessFile(destPath, "rw");
//设置本地文件大小
file.setLength(fileSize);
file.close();
//4.定位每个线程的下载位置,依次创建启动线程
for (int i = 0; i < threadNum; i++) {
//计算每个线程下载的开始位置
int startPos=i*currentPartSize;
//每个线程都需要使用RandomAccessFile对象进行下载
RandomAccessFile currentPart=new RandomAccessFile(destPath, "rw");
//定位该线程的下载位置
currentPart.seek(startPos);
//创建线程开始下载
threads[i]=new DownThread(startPos, currentPartSize, currentPart);
Thread t=new Thread(threads[i]);
t.start();
}
}
public double getCompleteRate(){
int sumSize=0;
for (int i = 0; i < threadNum; i++) {
sumSize+=threads[i].length;
}
return sumSize*1.0/fileSize;
}
private class DownThread implements Runnable{
//当前线程的下载位置
private int startPos;
//定义当前线程需要下载的文件大小
private int currentPartSize;
//定义该线程需要下载的文件块
private RandomAccessFile currentPart;
//定义该线程已下载的字节数
public int length;
public DownThread(int startPos, int currentPartSize, RandomAccessFile currentPart) {
this.startPos = startPos;
this.currentPartSize = currentPartSize;
this.currentPart = currentPart;
}
@Override
public void run() {
InputStream is= null;
try {
URL url=new URL(srcPath);
HttpURLConnection conn=(HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5*1000);
conn.setRequestMethod("GET");
conn.setRequestProperty("Accept", "image/gif,image/jpeg,image/pjpeg,image/png,"
+"application/x-shockwave-flash,application/xaml+xml,"
+"application/vnd.ms-xpsdocument,application/x-ms-xbap,"
+"application/x-ms-application,application/vnd.ms-excel,"
+"application/vnd.ms-powerpoint,application/msword,*/*");
conn.setRequestProperty("Accept-Language", "zh-CN");
conn.setRequestProperty("Charset", "UTF-8");
is = conn.getInputStream();
is.skip(this.startPos);
byte[] b=new byte[1024];
int len=0;
while(length<currentPartSize&&(len=is.read(b))!=-1){
currentPart.write(b,0,len);
length+=len;
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
currentPart.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
`
MultithreadDownload md=new MultithreadDownload( "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fup.enterdesk.com%2Fedpic%2Fa2%2Fdd%2F26%2Fa2dd26bd29e5191065d08c84770bef17.jpg&refer=http%3A%2F%2Fup.enterdesk.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1632538380&t=247ca694c9ecaf62fac0c702eb0fb71b", "E:\tempBy\a.jpg", 5); try { md.download(); new Thread(()->{while(md.getCompleteRate()<1){ System.out.println("已完成"+md.getCompleteRate()); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } }}).start(); md.getCompleteRate(); } catch (IOException e) { e.printStackTrace(); }
这段代码是多线程下载文件的核心逻辑,简单来说:
- 创建
URL对象。 - 获取连接
openConncetion()。 - 获取文件大小。
- 创建本地空文件。
- 计算每个线程的下载位置。
- 创建并启动多个线程下载。
GET和POST请求:
- GET:参数在URL里,明文,不安全,有长度限制。
- POST:参数在请求体里,相对安全,无长度限制。
代码示例:
public void getTest() throws IOException { URL url=new URL("https://baike.baidu.com/item/txt/1217330?fr=aladdin"); HttpURLConnection huc =(HttpURLConnection) url.openConnection(); //设置通用请求属性 huc.setRequestProperty("accept", "*/*"); huc.setRequestProperty("connection", "Keep-Alive"); huc.setRequestProperty("user-agent", "Mozilla/4.0(compatible;MSIE 6.0;Windows NT 5.1;SV1)"); //建立实际连接 huc.connect(); Map<String, List<String>> headerFields = huc.getHeaderFields(); for (String s : headerFields.keySet()) { System.out.println(s+"---->"+headerFields.get(s)); } BufferedReader in = new BufferedReader(new InputStreamReader(huc.getInputStream(),"UTF-8")); BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(new FileOutputStream("E:/Documents/a.html"),"UTF-8")); String line; String result=""; while((line=in.readLine())!=null){ result+=" "+line; bw.write(result); //System.out.println(result); } }
public void postTest() throws IOException { URL url=new URL("https://baike.baidu.com/item/txt/1217330?fr=aladdin"); HttpURLConnection huc =(HttpURLConnection) url.openConnection(); //设置通用请求属性 huc.setRequestProperty("accept", "*/*"); huc.setRequestProperty("connection", "Keep-Alive"); huc.setRequestProperty("user-agent", "Mozilla/4.0(compatible;MSIE 6.0;Windows NT 5.1;SV1)"); //发送POST请求 huc.setDoOutput(true); huc.setDoInput(true); PrintWriter out = new PrintWriter(huc.getOutputStream()); out.println("name=crazyit.org&pass=leegang"); out.flush(); BufferedReader in = new BufferedReader(new InputStreamReader(huc.getInputStream(),"UTF-8")); String result=""; String line; while((line=in.readLine())!=null){ result+=" "+line; //System.out.println(result); } }
3. Socket编程:网络通信的基石
Socket,IP地址和端口的组合,网络通信的灵魂。
客户端用Socket连接服务器,服务端用ServerSocket监听连接。
Socket:
Socket(InetAddress address, int port):连接服务器。getInputStream():获取输入流。getOutputStream():获取输出流。
ServerSocket:
ServerSocket(int port):监听端口。Socket s = accept():接收客户端连接。getInputStream():获取输入流。getOutputStream():获取输出流。
常用构造器及方法
//两个构造器都是用于创建连接到指定服务器(IP和端口)的Socket,该构造器没有指定本地主机ip和本地端口,使用默认IP地址和系统动态分配端口 Socket(InetAddress remoteAddress,int port) Socket(String remoteAddress,int port)
//两个构造器都是用于创建连接指定服务器的Socket,指定了本地IP和端口,这样适用于本地主机多IP地址情况 Socket(InetAddress remoteAddress,int port,InetAddress localAddress,int localPort) Socket(String remoteAddress,int port,InetAddress localAddress,int localPort)
InputStream getInputSream()//返回该Socket对象对应的输入流,让程序通过该输入流从Socket中取出数据 OutputStream getOutputStream()//返回该Socket对象对应的输出流,让程序通过该输出流向Socket中输出数据
ServerSocket常用方法
ServerSocket(int port)//创建ServerSocket并开启监听端口,用于接收其他通信主机向此端口发送的数据 ServerSocket(int port,int backlog)//增加了一个用于改变连接队列长度的参数backlog ServerSocket(int port,int backlog,InetAddress localAddr)//在机器存在多个IP地址的情况下,允许通过localAddr参数来指定将ServerSocket绑定到指定的IP地址
Socket accpet()//接收一个客户端Socket的连接请求,该方法将返回一个与客户端Socket对应的Socket,如果持续未得到客户端的连接请求,则会一直处于等待状态,线程也会被阻塞
客户端发送信息->服务器
代码示例:
`/*
* @Description:模拟客户端向服务器发送信息--客户端
* 1.创建Socket--指定IP和端口
* 2.获取输出流--将数据输出到服务器中
* 3.操作输出流
* 4.关闭连接--包括Socket、输出流
* @Param:
* @return: void
/
public void client(){
Socket s= null;
OutputStream os= null;
try {
//1.给客户端的Socket指定服务器端端的IP和端口号--第一要素
InetAddress ias=InetAddress.getByName("192.168.31.164");//这一步是多余的,这里为了表示InetAddress这个类的实例指向的是一个实际IP
s = new Socket(ias,8894);

黑客/网络安全学习包


资料目录
-
成长路线图&学习规划
-
配套视频教程
-
SRC&黑客文籍
-
护网行动资料
-
黑客必读书单
-
面试题合集
因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取
*************************************CSDN大礼包:《黑客&网络安全入门&进阶学习资源包》免费分享*************************************
1.成长路线图&学习规划
要学习一门新的技术,作为新手一定要先学习成长路线图,方向不对,努力白费。
对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图&学习规划。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。


因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取
*************************************CSDN大礼包:《黑客&网络安全入门&进阶学习资源包》免费分享*************************************
2.视频教程
很多朋友都不喜欢晦涩的文字,我也为大家准备了视频教程,其中一共有21个章节,每个章节都是当前板块的精华浓缩。


因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取
*************************************CSDN大礼包:《黑客&网络安全入门&进阶学习资源包》免费分享*************************************
3.SRC&黑客文籍
大家最喜欢也是最关心的SRC技术文籍&黑客技术也有收录
SRC技术文籍:

黑客资料由于是敏感资源,这里不能直接展示哦!
4.护网行动资料
其中关于HW护网行动,也准备了对应的资料,这些内容可相当于比赛的金手指!
5.黑客必读书单
**

**
6.面试题合集
当你自学到这里,你就要开始思考找工作的事情了,而工作绕不开的就是真题和面试题。

更多内容为防止和谐,可以扫描获取~

因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取
*************************************CSDN大礼包:《黑客&网络安全入门&进阶学习资源包》免费分享*********************************
从零基础入门到精通,收藏这篇就够了!&spm=1001.2101.3001.5002&articleId=148583533&d=1&t=3&u=b1605d12ff17480e92b8e8fb293d73ba)
700

被折叠的 条评论
为什么被折叠?



