26.02_网络编程三要素之IP概述(掌握)
- 每个设备在网络中的唯一标识
- 每台网络终端在网络中都有一个独立的地址,我们在网络中传输数据就是使用这个地址。
-
ipconfig
:查看本机IP192.168.12.42 -
ping
:测试连接192.168.40.62 - 本地回路地址:127.0.0.1 , 255.255.255.255是广播地址
- IPv4:4个字节组成,4个0-255。大概42亿,30亿都在北美,亚洲4亿。2011年初已经用尽。
- IPv6:8组,每组4个16进制数。
1a2b:0000:aaaa:0000:0000:0000:aabb:1f2f
-
1a2b::aaaa:0000:0000:0000:aabb:1f2f
//两个::代表省略了中间的0 1a2b:0000:aaaa::aabb:1f2f
26.03_网络编程三要素之端口号概述(掌握)
- 每个程序在设备上的唯一标识
- 每个网络程序都需要绑定一个端口号,传输数据的时候除了确定发到哪台机器上,还要明确发到哪个程序。
- 端口号范围从
0-65535
- 编写网络应用就需要绑定一个端口号,尽量使用1024以上的,1024以下的基本上都被系统程序占用了。
mysql: 3306
oracle: 1521
web: 80
tomcat: 8080
QQ: 4000
feiQ: 2425
26.04_网络编程三要素协议(掌握)
- 为计算机网络中进行数据交换而建立的规则、标准或约定的集合。
- UDP (类似发短信,对方可以不开机,甚至是假号码)
- 面向无连接,数据不安全,速度快。不区分客户端与服务端。
- TCP (类似打电话,拨通才能打通话,http的底层就是TCP)
* 面向连接(三次握手),数据安全,速度略低。分为客户端和服务端。- 三次握手: 1客户端先向服务端发起请求, 2服务端响应请求, 3传输数据
26.05_Socket通信原理图解(了解)
- 网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能识别的标识符套接字。
- 通信的两端都有
Socket
。 - 网络通信其实就是
Socket
间的通信。 - 数据在两个
Socket
间通过IO流传输。 -
Socket
在应用程序中创建,通过一种绑定机制与驱动程序建立关系,告诉自己所对应的IP和port。
26.06_网络编程(UDP传输)(了解)
- 1.发送Send
byte[] d = "你好啊!".getBytes();
InetAddress ip = InetAddress.getByName("127.0.0.1");
DatagramSocket socket = new DatagramSocket(); //创建socket,相当于是码头,随机端口号
// 四个参数是: 数据、数据长度、地址、端口号
DatagramPacket data = new DatagramPacket(d, d.length, ip, 3001);
socket.send(data);
- 2.接收Receive
DatagramSocket socket = new DatagramSocket(3001); //指定端口号,创建socket,相当于创建码头
DatagramPacket data = new DatagramPacket(new byte[1024], 1024); //相当于创建集装箱
socket.receive(data);
socket.close();
byte[] arr = data.getData(); //获取数据
int len = data.getLength(); //获取有效的字节个数
System.out.println(new String(arr, 0,len));
- 3.接收方获取ip和端口号
String ip = packet.getAddress().getHostAddress();
int port = packet.getPort();
26.07_网络编程(UDP传输优化)
- 接收端Receive
DatagramSocket socket = new DatagramSocket(3001); //指定端口号,创建socket,相当于创建码头
DatagramPacket data = new DatagramPacket(new byte[1024], 1024); //相当于创建集装箱
while(true) {
socket.receive(data);
byte[] arr = data.getData(); //获取数据
int len = data.getLength(); //获取有效的字节个数
System.out.println("收到内容: " + new String(arr, 0,len));
System.out.println("对方地址: " + data.getAddress().getHostAddress());
System.out.println("端口: " + data.getPort() + "\r\n");
}
- 发送端Send
Scanner sc = new Scanner(System.in);
System.out.println("请输入发送的内容:");
DatagramSocket socket = new DatagramSocket(); //创建socket,相当于是码头
InetAddress ip = InetAddress.getByName("127.0.0.1");
while(true) {
String line = sc.nextLine();
if ("q".equals(line)) break;
byte[] d = line.getBytes(); //数据
// 四个参数是: 数据、数据长度、地址、端口号
DatagramPacket data = new DatagramPacket(d, d.length, ip, 3001);
socket.send(data); //发货
}
socket.close(); //底层是IO流,所以应该也关掉
sc.close();
也可以开启两个线程,一个线程发送信息,一个线程接收消息。
26.xx_GUI小程序遇到的懵逼知识点
这中间有一个GUI的聊天小程序,但是代码很多,就不粘贴了,毕竟Java桌面编程不是重点,目标是JavaEE,这里就将里面遇到的疑问点整理一下。
1.快捷键 Alt + Shift + L 把选中的变成局部变量
Alt + Shift + z 选中代码,按此快捷键 快速try
Ctrl+Shift+Numpad_Divede(小键盘的/号) 折叠全部方法
Ctrl+Shift+Numpad_Multiply(小键盘的*号) 展开全部方法
2.匿名内部类里可以直接调用外部类的方法。
// 如下例子,写全的方式为: ClassName.this.method(); ClassName为外部类的名字
new Runnable() {
public void run(){
method();
}
};
2.1 如果外部变量是外部类的本地变量(如在方法中定义的变量),
必须声明成final才能在内部类中使用,正常是不可以修改这个变量的,
但如果变量搜索是对象,可以修改对象内的属性
2.2 如果外部变量是外部类的成员变量或类变量,内部类可以直接修改
3. 最常见的基本类型数组写法: int[] a = {1,2,3}; byte[] b = {1,2,3};
这种写法的全写法是: int[] a = new int[]{1,2,3}; byte[] b = new byte[]{1,2,3}
所以见到 String str = new String(new byte[]{1,2,3}); 不应该懵逼,这仅仅是标准写法
26.15_生成jar文件
Eclipse
下,生成jar文件
顺序是:
1.项目或类上右键 --> Export --> Java下的JAR file
2.选择好要导出jar的类和导出位置,点击Next>
3.再次点击Next>
4.选择Main Class之后,点击Finish
26.16_网络编程(TCP协议)(掌握)
- 1.客户端
- 创建
Socket
连接服务端(指定ip地址,端口号)通过ip地址找对应的服务器 - 调用
Socket
的getInputStream()
和getOutputStream()
方法获取和服务端相连的IO流 - 输入流可以读取服务端输出流写出的数据
- 输出流可以写出数据到服务端的输入流
- 创建
- 2.服务端
- 创建
ServerSocket
(需要指定端口号) - 调用
ServerSocket的accept()
方法接收一个客户端请求,得到一个Socket
- 调用
Socket
的getInputStream()
和getOutputStream()
方法获取和客户端相连的IO流 - 输入流可以读取客户端输出流写出的数据
- 输出流可以写出数据到客户端的输入流
- 创建
26.17_网络编程(TCP协议代码优化)
- 客户端
Socket socket = new Socket("127.0.0.1", 3001); //指定ip和端口号
// 将InputStream 包装成 BufferedReader 便于直接读取一行数据
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// 将OutputStream 包装成 PrintStream 好处是能直接写出换行和字符串
PrintStream ps = new PrintStream(socket.getOutputStream());
System.out.println(br.readLine()); //读取服务器的回话
ps.println("我是客户端,我就是想打个招呼而已。。"); //向服务器回话
socket.close();
- 服务端
ServerSocket sever = new ServerSocket(3001); //指定端口号
Socket socket = sever.accept(); //接收客户端的请求
// 将InputStream 包装成 BufferedReader 便于直接读取一行数据
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// 将OutputStream 包装成 PrintStream 好处是能直接写出换行和字符串
PrintStream ps = new PrintStream(socket.getOutputStream());
ps.println("你好,我是服务器,有什么事?");
System.out.println(br.readLine()); //读取客户端的回复
26.18_网络编程(服务端是多线程的)(掌握)
ServerSocket sever = new ServerSocket(3001); //指定端口号
while(true) {
final Socket socket = sever.accept(); //接收客户端的请求
new Thread(){
public void run() {
try {
// 将InputStream 包装成 BufferedReader 便于直接读取一行数据
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// 将OutputStream 包装成 PrintStream 好处是能直接写出换行和字符串
PrintStream ps = new PrintStream(socket.getOutputStream());
ps.println("你好,我是服务器,有什么事?");
System.out.println(br.readLine()); //读取客户端的回复
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
}
26.19_网络编程(练习)
- 客户端向服务器写字符串(键盘录入),服务器(多线程)将字符串反转后写回,客户端再次读取到是反转后的字符串
//反转字符串
private String reverString(String str) {
return new StringBuffer(str).reverse().toString();
}
26.20_网络编程(客户端向服务器上传文件练习)
- 客户端部分代码
Socket socket = new Socket("192.168.3.109",3002);
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintStream ps = new PrintStream(socket.getOutputStream());
ps.println(file.getName()); // 发送文件名到服务端
String result = br.readLine(); //读取服务器返回结果
if ("存在".equals(result)) {
System.out.println("您上传的文件已经存在,请不要重复上传..");
socket.close();
return;
}
System.out.println("文件不存在,开始上传...");
FileInputStream fis = new FileInputStream(file); //开始读取文件到服务器
byte[] data = new byte[10 * 1024];
int len ;
while( (len = fis.read(data)) != -1) {
ps.write(data, 0, len);
}
fis.close();
socket.close();
- 服务端部分代码
ServerSocket server = new ServerSocket(3002);
System.out.println("服务器启动,端口号 3002 ");
while(true) {
final Socket socket = server.accept();
System.out.println("收到" + socket.getInetAddress().getHostAddress()+ "的请求,开始处理...");
new Thread(){
public void run() {
try {
InputStream is = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
PrintStream ps = new PrintStream(socket.getOutputStream());
String fileName = br.readLine();
File dir = new File("/Users/houwan/Java");
if (!dir.exists()) dir.mkdir(); //不存在就创建文件夹
File file = new File(dir, fileName); //封装成File对象
if (file.exists()) {
ps.println("存在");
socket.close(); //关闭此次服务
return;
}else ps.println("不存在");
System.out.println("客户端开始上传文件...");
FileOutputStream fos = new FileOutputStream(file); //读取客户端上传的文件,保持到本地
byte[] data = new byte[10 * 1024];
int len ;
while ( (len = is.read(data)) != -1) {
fos.write(data, 0, len);
}
fos.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
};
}.start();
}
END。
我是小侯爷。
在魔都艰苦奋斗,白天是上班族,晚上是知识服务工作者。
如果读完觉得有收获的话,记得关注和点赞哦。
非要打赏的话,我也是不会拒绝的。