JAVA 网络编程 笔记
程序员文章站
2022-03-05 15:42:30
...
网络编程
1.1 概述
网络编程需要什么:
-
准确的定位网络上的一台主机的ip地址和端口号,定位到这个计算机上的某个资源
-
找到了这个主机,如何传输数据
Java web: 网页编程 B/S
网络编程:TCP/IP C/S
1.2 网络通信的要素
-
网络编程中有两个主要的问题
- 如何准确的定位到网络上的一台或多台主机
- 找到主机之后如何进行通信
-
网络编程中的要素
- IP和端口号
- 通信协议:TCP UDP
-
万物皆对象
1.3 IP
IP地址:InetAddress
-
唯一定位一台网络上的计算机
-
127.0.0.1:本机localhost
-
ip地址分类
- ipv4/ipv6:
- ipv4 4个字节,每个字节0~255,共42亿,30亿在北美
- ipv6 128位,8个无符号整数:2001:2001:2001:2001:2001:2001:2001:2001
- 公网(互联网)/ 私网(局域网)
- ABCDE类地址
- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rTD0bN2a-1605444193708)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201115202847325.png)]
- 192.168.xx.xx,专门给组织内部使用
- ipv4/ipv6:
1.4 端口
- 0~65535
- TCP/UDP: 65535*2,单个协议下,端口不能冲突
- 端口分类
- 公有端口,尽量不要占用:0~1023
- https: 443
- http: 80
- ftp: 21
- telent:23
- 程序注册端口:1024-49151,分配用户或者程序
- Tomcat:8080
- MySQL:3306
- Oracle:1521
- 动态、私有端口:49152-65535
- 公有端口,尽量不要占用:0~1023
netstat -ano#查看所有端口
netstat -ano|findstr "5900"#参看指定的端口
tasklist|finderstr “8696” #查看指定端口(8696)的进程
1.5 通信协议
网络通信协议:速率,传输码率,代码结构,传输控制…
TCP/IP协议簇:实际上是一组协议
重要:
- TCP:用户传输协议 打电话
- UDP:用户数据报协议 发短信
1.6 TCP实现聊天
客户端
package com.kuang.lesson02;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.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;
//创建一个socket连接
socket =new Socket(serverIP,port);
//发送消息
os=socket.getOutputStream();
os.write("你好,欢迎光临".getBytes());
}catch (IOException e) {
// TODO Auto-generated catch block
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();
}
}
}
}
}
服务端
package com.kuang.lesson02;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
//服务端
public class TcpServerDemo01 {
public static void main(String[] args) {
ServerSocket serverSocket = null;
Socket socket = null;
InputStream is = null;
ByteArrayOutputStream baos = null;
try {
//1.有一个地址:localhost:9999
serverSocket = new ServerSocket(9999);
while(true) {
//2. 等待客户端连接
socket = serverSocket.accept();
//3.读取客户端的消息
is = socket.getInputStream();
//4. 管道流:避免乱码
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 (Exception 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(socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(serverSocket != null) {
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
1.7 TCP文件上传
客户端
package com.kuang.lesson02;
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
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("a.jpg"));
//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());
baos.close();
inputStream.close();
fis.close();
os.close();
socket.close();
}
}
服务端
package com.kuang.lesson02;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class TcpServerDemo02 {
public static void main(String[] args) throws Exception {
// 1. 创建服务
ServerSocket serverSocket = new ServerSocket(9000);
// 2. 监听客户端的连接
Socket socket = serverSocket.accept();
// 3. 获取输入流
InputStream is = socket.getInputStream();
// 4. 文件输出
FileOutputStream fos = new FileOutputStream(new File("b.jpg"));
byte[] buffer = new byte[1024];
int len;
while((len = is.read(buffer)) != -1) {
fos.write(buffer,0, len);
}
// 5. 通知客户端已经接收完毕
OutputStream os = socket.getOutputStream();
os.write("接收完毕".getBytes());
fos.close();
is.close();
socket.close();
serverSocket.close();
}
}
1.9 UDP消息发送
客户端
package com.kuang.lesson03;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
public class UdpClientDemo01 {
public static void main(String[] args) throws Exception {
// 创建Socket
DatagramSocket socket = new DatagramSocket();
// 建包
String msg = "你好,世界";
InetAddress localhost = InetAddress.getByName("localhost");
int port = 9090;
DatagramPacket packet = new DatagramPacket(msg.getBytes(),0,msg.length(),localhost,port);
//发送包
socket.send(packet);
}
}
服务端
package com.kuang.lesson03;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.util.Arrays;
public class UdpServerDemo01 {
public static void main(String[] args) throws Exception {
//开放端口
DatagramSocket socket = new DatagramSocket(9090);
//接收数据
byte[] buffer = new byte[4096];
DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);
socket.receive(packet); //阻塞接收
System.out.println(packet.getAddress().getHostAddress());
System.out.println(packet.getLength());
String s = new String(packet.getData(),0,packet.getLength());
System.out.println(s);
//关闭连接
socket.close();
}
}
总结
在1.9 UDP传输那块,当客户端建包下的msg为中文时,服务端会出现包的长度正确,但是打印不全的情况,。当msg为英文时,则不会出现该情况,目前推测是编码导致的。
上一篇: 1351 统计有序矩阵中的负数
下一篇: JAVA笔记18 网络编程