Java网络编程
- 网络编程:
- 计算机网络:
- 网络编程:
- 网络模型:
- 网络编程三要素:
- IP地址:
- 端口号:
- 协议:
- TCP协议:
- TCP三次握手 和 四次挥手:
- 三次握手:
- 四次挥手:
- 案例:
- 传输文件:
- 单聊:
- 群聊:
- UDP协议:
- 客户端之间收发数据:
- UDP案例 之 单聊:
- HTTP协议:
- 案例:
- 获取淘宝商品周边类别:
- 下载图片:
- InetAddress类:
- Socket:
网络编程:
网络编程:多台计算机互相传输数据。
计算机网络:
计算机网络:指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路和通信设备连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。
网络编程:
实现多台计算机之间实现数据的共享和传递。
网络应用程序主要组成为:网络编程+IO流+多线程(三大技术)。
网络模型:
网络模型:两台计算机之间的通信是根据什么规则来走的。
分为:OSI模型(理想中的模型)和TCP/IP模型(实际应用的模型)。
想深入学习的可以学习《TCP/IP详解》《TCP协议簇》书籍。
网络编程三要素:
网络通讯的模型:请求-响应,客户端-服务端。
三要素:IP地址,端口,协议(数据传输的规则)。
IP地址:
IP地址:网络中计算机的唯一标识(IP地址是一个32位的二进制数据,为了方便,将一个字节的二进制转换为一个十进制的数据)。
IP地址的组成:网络号段+主机段。
A类IP地址:第一段号码为网络号码,剩下的三段号码为本地计算机的号码----可以配置 256* 256 *256 台主机。
B类IP地址:前二段号码为网络号码,剩下的二段号码为本地计算机的号码。
C类IP地址:前三段号码为网络号码,剩下的一段号码为本地计算机的号码。
A类地址的表示范围为:0.0.0.0~126.255.255.255,默认网络屏蔽为:255.0.0.0;A类地址分配给规模特别大的网络使用。
A类网络用第一组数字表示网络本身的地址,后面三组数字作为连接于网络上的主机的地址。分配给具有大量主机(直接个人用户)而局域网络个数较少的大型网络。例如IBM公司的网络。
B类地址的表示范围为:128.0.0.0~191.255.255.255,默认网络屏蔽为:255.255.0.0;
C类地址的表示范围为:192.0.0.0~223.255.255.255,默认网络屏蔽为:255.255.255.0;C类地址分配给小型网络,如一般的局域网和校园网,它可连接的主机数量是最少的,采用把所属的用户分为若干的网段进行管理。
特殊地址:
127.0.0.1 回环地址,可用于测试本机的网络是否有问题。eg: ping 127.0.0.1
DOS命令 :ipconfig-------->查看本机IP地址
xxx.xxx.xxx.255 ------->广播地址
端口号:
端口号:正在运行的程序的标识。
tips:
1. 每个网络程序都会至少有一个逻辑端口。
2. 用于标识进程的逻辑地址,不同进程的标识不同。
3. 有效端口:065535,其中01024系统使用或保留端口。
4. 通过第三方工具可以查看。
端口与协议有关:
TCP和UDP的端口互不相干,同一个协议的端口不能重复,不同协议的端口号可以重复。
协议:
协议:通信规则,就是数据的传输规则。
TCP 与 UDP区别:
TCP、UDP都是传输层的协议。
TCP:建立连接,形成传输数据的通道;在连接中进行大数据量传输;通过三次握手完成连接,是可靠协议;必须建立连接,效率会稍低,例如:打电话。
UDP:将数据源和目的封装到数据包中,不需要建立连接;每个数据报的大小在限制在64k;因无连接,是不可靠协议;不需要建立连接,速度快:例如发短信。
区别 | TCP | UDP |
---|---|---|
是否连接 | 面向连接 | 无面向连接 |
传输可靠性 | 可靠 | 不可靠 |
应用场合 | 传输大量数据 | 少量数据 |
速度 | 慢 | 快 |
TCP协议:
服务端和客户端交互。
TCP协议:建立连接,形成传输数据的通道;在连接中进行大数据量传输;通过三次握手完成连接,是可靠协议;必须建立连接,效率会稍低,例如:打电话。
TCP三次握手 和 四次挥手:
三次握手:
四次挥手:
案例:
传输文件:
//服务端
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(8080);
Socket socket = server.accept();
//接收的文件
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
//把接收的文件存入本地文件中
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy.mp4"));
byte[] bs = new byte[1024];
int len;
while((len = bis.read(bs)) != -1){
bos.write(bs, 0, len);
}
bis.close();
bos.close();
server.close();
}
}
//客户端
public class Client {
public static void main(String[] args) throws UnknownHostException, IOException {
Socket socket = new Socket("127.0.0.1", 8080);
//准备发送的本地文件
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("Original.mp4"));
//发送的文件
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
byte[] bs = new byte[1024];
int len;
while((len = bis.read(bs)) != -1){
bos.write(bs, 0, len);
}
bis.close();
bos.close();
socket.close();
}
}
单聊:
只能一人一句话的来,只能客户端先发。
//服务端
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(8080);
Socket socket = server.accept();
Scanner scan = new Scanner(System.in);
//接收的信息
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream(), "GBK"));
//发送的信息
PrintStream ps = new PrintStream(socket.getOutputStream());
while(true){
String readLine = br.readLine();
System.out.println(readLine);
ps.println("小红:" + scan.next());
}
}
}
//客户端
public class Client {
public static void main(String[] args) throws UnknownHostException, IOException {
Socket socket = new Socket("127.0.0.1", 8080);
Scanner scan = new Scanner(System.in);
//发送的信息
PrintStream ps = new PrintStream(socket.getOutputStream());
//接收的信息
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream(), "GBK"));
while(true){
ps.println("小明:" + scan.next());
String readLine = br.readLine();
System.out.println(readLine);
}
}
}
优化单聊:一人可以多句话,随便谁先发。
发送消息在主线程,接受消息在子线程。
//接收线程
public class ReceiveThread extends Thread{
private Socket socket;
public ReceiveThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
//接收的消息
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream(), "GBK"));
while(true){
//输出接收的消息
String readLine = br.readLine();
System.out.println(readLine);
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//服务端
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(8080);
Socket socket = server.accept();
new ReceiveThread(socket).start();
Scanner scan = new Scanner(System.in);
PrintStream ps = new PrintStream(socket.getOutputStream());
while(true){
ps.println("小红:" + scan.next());
}
}
}
//客户端
public class Client {
public static void main(String[] args) throws UnknownHostException, IOException {
Socket socket = new Socket("127.0.0.1", 8080);
new ReceiveThread(socket).start();
Scanner scan = new Scanner(System.in);
PrintStream ps = new PrintStream(socket.getOutputStream());
while(true){
ps.println("小明:" + scan.next());
}
}
}
群聊:
public class ReceiveThread extends Thread{
private Socket socket;
public ReceiveThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
//接收的消息
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream(), "GBK"));
while(true){
//输出接收的消息
String readLine = br.readLine();
System.out.println(readLine);
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class ServerThread extends Thread{
private Socket socket;
public ServerThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
//接受当前客户端的消息
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream(), "GBK"));
while(true){
String readLine = br.readLine();
System.out.println(readLine);
//发送给其他客户端消息
Set<Entry<String,PrintStream>> entrySet = Server.map.entrySet();
for (Entry<String, PrintStream> entry : entrySet) {
String ip = entry.getKey();
PrintStream ps = entry.getValue();
if(!socket.getInetAddress().toString().equals(ip)){
//当前Socket的IP地址和容器里的IP地址不同的时候,
//输出当前Socket的接收的信息给其他客户端。
ps.println(readLine);
}
}
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//服务端
public class Server {
public static final ConcurrentHashMap<String, PrintStream> map = new ConcurrentHashMap<>();
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(8080);
while(true){
//接收客户端的连接,创建Socket对象。
Socket socket = server.accept();
//客户端ip地址
String ip = socket.getInetAddress().toString();
//打印流,当前Socket接收的信息,要发送给其他客户端的信息。
PrintStream ps = new PrintStream(socket.getOutputStream());
//放入容器中
map.put(ip, ps);
//每创建一个Socket对象,就创建一个服务端线程。
new ServerThread(socket).start();
}
}
}
//客户端
public class Client {
public static void main(String[] args) throws UnknownHostException, IOException {
Socket socket = new Socket("127.0.0.1", 8080);
new ReceiveThread(socket).start();
Scanner scan = new Scanner(System.in);
PrintStream ps = new PrintStream(socket.getOutputStream());
while(true){
ps.println("小明:" + scan.next());
}
}
}
UDP协议:
客户端和客户端交互。
UDP协议:将数据源和目的封装到数据包中,不需要建立连接;每个数据报的大小在限制在64k;因无连接,是不可靠协议;不需要建立连接,速度快:例如发短信。
客户端之间收发数据:
tips:
- UDP协议的Socket是DatagramSocket。
- 7070表示的是自己的端口号,不是对方的端口号。
public class Client01 {
public static void main(String[] args) throws IOException {
//自己的端口号
DatagramSocket socket = new DatagramSocket(7070);
//1.向客户端2发送数据
byte[] buf = "今天天气真好!!!".getBytes();
//对方的IP地址和端口号
DatagramPacket p = new DatagramPacket(buf , 0, buf.length, InetAddress.getByName("127.0.0.1"), 8080);
//发送数据
socket.send(p);
//4.接受来自客户端1的数据
buf = new byte[1024];
//接收1024字节的信息
p = new DatagramPacket(buf , buf.length);
//接收数据
socket.receive(p);
//去掉首尾空格。
System.out.println(new String(buf).trim());
socket.close();
}
}
public class Client02 {
public static void main(String[] args) throws IOException {
DatagramSocket socket = new DatagramSocket(8080);
//2.接受来自客户端1的数据
byte[] buf = new byte[1024];
DatagramPacket p = new