一、笔记
网络编程
网络编程常识
•网络编程:数据在网络中的传输(网络通讯、通信)
•常见的网络通讯软件:QQ 微信 陌陌 YY QT TQ msn 飞信 飞秋 .......
•7层网络模型
为了保证数据传输的可靠安全性,ISO(International Standardization Organization)国际标准化组织将数据的传输从逻辑上划分为7层
应用层、表示层、会话层、传输层、网络层、数据链路层、物理层
在发送数据之前要按照上述七层协议从上到下一层一层进行加包处理,再发送出去;
在接收数据之后要按照上述七层协议从下到上一层一层进行拆包处理,再解析出来;
•常用的协议(了解)
http/https协议 -超文本传输协议,主要用于浏览网页时使用
ftp协议 -文件传输协议,主要用于上传和下载文件时使用
tcp协议 -传输控制协议,主要用于网络通信时使用
udp协议 -用户数据报协议,主要用于网络通信时使用
ip协议 -互联网协议,是上述所有协议的底层协议
协议本质上是一种约定,用于规范通信双方的方式和规则。
TCP/IP协议
传输控制协议/互联网协议:将网络模型化分为四层:
应用层(表示层、会话层)、传输层、网络层、链路层(数据层、物理层)
链路层:链路层是用于定义物理传输通道,通常是对某些网络连接设备的驱动协议,例如针对光纤、网线提供的驱动。
网络层:网络层是整个TCP/IP协议的核心,它主要用于将传输的数据进行分组,将分组数据发送到目标计算机或者网络。
传输层:主要使网络程序进行通信,在进行网络通信时,可以采用TCP协议,也可以采用UDP协议
应用层:主要负责应用程序的协议,例如HTTP协议、FTP协议、file等
IP地址
如:
192.168.1.1 - 是绝大多数路由器的登录地址
127.0.0.1 - 是本地主机地址
•IP地址本质上就是互联网中的唯一地址标识,通常由32位二进制组成的无符号整数进行描述,叫做IPv4,当然也有128位二进制组成的整数,叫做IPv6。
•日常生活中采用点分十进制表示法来进行IP地址的描述,也就是将每个字节的二进制转换为十进制整数,不同整数之间采用小数点隔开。
查询IP地址的方式:
Windows系统:在dos窗口中使用ipconfig命令或ipconfig/all命令查看即可.
Linux系统: 在终端窗口中使用ifconfig命令或/sbin/ifconfig命令查看即可.
端口号
• IP地址 - 使用IP地址可以定位到具体某台设备。
•端口号 - 可以定位到具体设备中的具体进程
端口号本质就是由16位二进制组成的整数,范围是:0 ~ 65535,其中0 ~ 1024之间的端口号通常被系统占用,因此编程从1025开始使用
一个IP对应一台电脑...
一个端口号对应一个软件
InetAddress类
•JAVA中提供了一个InetAdderss类,该类用于封装一个IP地址,并提供了一系列与IP地址相关的方法。
URLEncoder和URLDecoder
•主要用于将中文字符串转换为可传输的字符串
static String encode(String s, String enc)
用于将中文字符串转换为可传输的字符串,并指定字符集。编码
static String decode(String s, String enc)
用于将编码后的字符串转换为中文字符串,并指定编码时的字符集。解码
UDP协议
•UDP是无连接通信协议,即在数据传输时,数据的发送端和接收端不建立逻辑连接。简单来说,当一台计算机向另外一台计算机发送数据时,发送端不会确认接收端是否存在,就会发出数据,同样接收端在收到数据时,也不会向发送端反馈是否收到数据。
•由于使用UDP协议消耗资源小,通信效率高,所以通常都会用于音频、视频和普通数据的传输例如视频会议都使用UDP协议,因为这种情况即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。
•UDP会将发送的数据打包,包的最大不能超过64kb
UDP通信实现
•DatagramPacket(打包、拆包)
•DatagramSocket(发包、收包)
发送端(send)
1.需要数据:byte[]
2.将数据打包:
DatagramPacket(byte[] buf, int length, InetAddress address, int port)
3.需要将打包后的数据发送出去,前提:需要码头
DatagramSocket()
4.发送数据
void send(DatagramPacket p)
5.关闭资源
void close()
接收端(Receive)
1.创建接收数据的平台
DatagramSocket(int port)
2.创建一个存放数据包的仓库:byte[]
3.将接收来的数据进行拆包:前提:需要有拆包工具
DatagramPacket(byte[] buf, int length)
4.真正意义的接包
void receive(DatagramPacket p)
5.拆包:调用 DatagramPacket方法
byte[] getData() int getLength()
6. 关闭资源
TCP通信实现
•TCP通信同UDP通信一样,都能实现两台计算机之间的通信,通信的两端都需要创建socket对象。
•而TCP通信是严格区分客户端与服务器端的,在通信时,必须先由客户端去连接服务器端才能实现通信,服务器端不可以主动连接客户端,并且服务器端程序需要事先启动,等待客户端的连接。
•通信时,首先创建代表服务器端的ServerSocket对象,该对象相当于开启一个服务,并等待客户端的连接,然后创建代表客户端的Socket对象向服务器端发出连接请求,服务器端响应请求,两者建立连接开始通信。”三次握手”、”四次挥手”
•ServerSocket类,用于表示服务器端
•Socket类,用于表示客户端
客户端(Client)
1.需要创建客户端
Socket(InetAddress address, int port)
2.获取流对象
getOutputStream()
3.使用流发送数据
4.关闭资源
服务器(Server)
1.创建服务器
ServerSocket(int port)
2.获取流对象:前提:获取Socket对象
accept()
3.获取流对象
getInputStream()
4.获取客户端传来的数据
5.关闭资源
1.创建服务器
ServerSocket(int port)
2.获取流对象:前提:获取Socket对象
accept()
3.获取流对象
getInputStream()
4.获取客户端传来的数据
5.关闭资源
二、实践
1.tcp
package com.qfedu.zhuguangyi.socket_tcp;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
public class TCPClient {
/*
* 客户端
*/
public static void main(String[] args) {
Socket s = null;
OutputStream os = null;
InputStream is = null;
try {
Thread.currentThread().sleep(5000);
//1.创建客户端对象 Socket(InetAddress address, int port)
s = new Socket(InetAddress.getByName("10.9.151.86"),6688);
//2.获取流对象
os = s.getOutputStream();
//3.往流中写入数据
os.write("你好啊,服务器!".getBytes());
/*
* 客户端接收从服务器返回的消息
* 1.获取流 InputStream
* 2.读取数据
* 3.关闭资源
*/
is = s.getInputStream();
byte[] b = new byte[1024];
int len = is.read(b);
System.out.println(new String(b,0,len));
}catch(Exception e) {
e.printStackTrace();
}finally {
//4.关闭资源
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
package com.qfedu.zhuguangyi.socket_tcp;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class TCPServer {
/*
* 服务器端
* 1.创建服务器端对象
* ServerSocket(int port)
* 2.获取Socket对象
accept()
3.获取流对象
InputStream getInputStream()
4.从流中将数据读取出来
read()
5.关闭资源
*/
public static void main(String[] args) throws Exception {
ServerSocket ss = new ServerSocket(6688);
while(true) {
Socket sk = ss.accept();//获取Socket对象
InputStream is = sk.getInputStream();
byte[] b = new byte[1024];
int i = is.read(b);
System.out.println(sk.getInetAddress()+":"+new String(b,0,i));
/*
* 服务器向客户端返回消息
* 1.获取流 OutputStream
* 2.写入
* 3.关闭资源
*/
OutputStream os = sk.getOutputStream();
os.write("客户端,我收到啦!!!!".getBytes());
}
//关闭资源
// os.close();
// is.close();
// sk.close();
// ss.close();
}
}
2.udp
package com.qfedu.zhuguangyi.socket_udp;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Scanner;
public class UDPSend {
/*
* 发送端====>接收端
* 1.有数据 byte[]
2.打包DatagramPacket
DatagramPacket(byte[] buf, int length, InetAddress address, int port)
3.需要平台
DatagramSocket()
4.发包
void send(DatagramPacket p)
5.关闭资源
close()
*/
public static void main(String[] args) throws Exception {
Scanner sc = new Scanner(System.in);
while(true) {
byte[] b =sc.next().getBytes();
InetAddress ip = InetAddress.getByName("10.9.151.86");
//(byte[] buf, int length, InetAddress address, int port)
//数据,数据的长度,地址,端口号
DatagramPacket dp = new DatagramPacket(b,b.length,ip,8866);
DatagramSocket ds = new DatagramSocket();//平台
ds.send(dp);//发送数据
}
// ds.close();
}
}
package com.qfedu.zhuguangyi.socket_udp;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class UDPReceive {
/* 接收端:
* 1.数据接收过来:前提得有平台
DatagramSocket(int port)
2.应该有个数据仓库:byte[]
3.拆包工具:
DatagramPacket(byte[] buf, int length)
4.将数据放入到拆包工具中:
void receive(DatagramPacket p)
5.拆包:
读取数据 数据的长度
6.关闭资源
*/
public static void main(String[] args) throws Exception {
DatagramSocket ds = new DatagramSocket(8866);
while(true) {
byte[] b = new byte[100];//仓库
DatagramPacket dp = new DatagramPacket(b,b.length);
//此时dp中才有了传输过来的数据包
ds.receive(dp);//有一个阻塞,用来接收数据。
/*
* 拆包
*/
byte[] data = dp.getData();//获取接收来的数据,返回一个byte类型的数组
int len = dp.getLength();//获取接收到的数据的长度
System.out.println(dp.getAddress()+":"+new String(data,0,len));//打印接收过来的数据
}
// ds.close();//关闭资源
}
}
最巨大的遗憾,是被命运安排!!!