UDP/TCP
网络编程
网络编程就是不同机器间的数据传输
电脑要上网必须有网线,网线是由网卡支持(硬件上)
每一个网卡有一个全球唯一的mac地址
网卡的物理地址通常是由网卡生产厂家烧入网卡中
它存储的是传输数据时真正赖以标识发出数据的电脑和
接收数据的主机的地址
在网络底层的物理传输过程中,是通过物理地址来识别主机的
IP协议:进行IP数据包的分割和组装
ip地址是可变的
1.为每一台计算机分配IP地址
2.确定哪些地址在同一个子网络
ip地址是服务商给你的,mac地址是你的网卡物理地址
arp协议:通过接受到的ip解析出对应的mac地址完成两台机器的通信
IP地址属于网络层,而MAC地址属于数据链路层
数据链路层协议可以使数据从一个节点传递到相同链路
的另一个节点(通过MAC地址)
网络层协议使数据可以从一个网络传递到另一个网络上
(ARP根据目的IP地址,找到中间节点的MAC地址,
通过中间节点传送,从而最终到达目的网络)
一个主机与另一个主机连接需要ip地址与mac地址经过一系列的协议和节点
才能联通,相互之间收发数据还需要主机上的应用来完成(例如QQ,飞秋等)
应用的启动就需要系统为这个应用开辟一个端口(例如mysql数据库默认端口为3306)
通过ip与端口就可以找到主机上的应用从而进行通信了
有了唯一的mac地址为什么还要有ip地址?(源自百度)
由于全世界存在着各式各样的网络,他们使用不同的硬件地址。
要使这些异构网络能够互相通信就必须进行 非常复杂的硬件地址转化
工作,因此由用户或用户主机来完成这项工作几乎是不可能的的事。
但IP编址就把这个复杂的问题解决了。连接到互联网的主机
只需要各自拥有一个唯一的IP地址,他们之间的通信就像连接在
同一个网络那么简单方便。因为ARP是由计算机软件自动进行的
,对用户来说是看不见这种调用过程的。
UDP协议
一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务
UDP提供了无连接通信,且不对传送数据包进行可靠性保证,
适合于一次传输少量数据,UDP传输的可靠性由应用层负责
//server端(简略)
package server;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class UDPServer {
public static void main(String[] args) throws IOException {
// 创建数据收发对象
DatagramSocket data = new DatagramSocket(3366);
// 创建字节数组接收发送的数据
byte[] b = new byte[1024];
while (true) {
// 创建数据封装对象
DatagramPacket packet = new DatagramPacket(b, b.length);
// 接收数据
data.receive(packet);
//获取客户端ip
String ip = packet.getAddress().getHostAddress();
//获取客户端端口
int port = packet.getPort();
// 获取要接收数据的字节长度
int len = packet.getLength();
//这一次存入的数据会覆盖数组中上一次存入的数据
//无法覆盖全部的数组长度时,剩下无法覆盖的数据仍旧在数组中
//只获取新存入数组的一部分数据
String string = new String(b, 0, len);
System.out.println(string + "..." + ip + " " + port);
System.out.println(string.length());
}
}
}
//client(简略)
DatagramSocket data = new DatagramSocket();
InetAddress address = InetAddress.getByName("127.0.0.1");
while (true) {
Scanner scanner = new Scanner(System.in);
String string = scanner.next();
byte[] buf = string.getBytes();
DatagramPacket da = new DatagramPacket(buf, buf.length, address, 3366);
data.send(da);
}
TCP协议
在主机间建立一个虚拟连接,以实现高可靠性的数据包交换
(ip协议与arp协议只能找对应的主机,不能保证通信的可靠性)
一个应用程序通过TCP协议与另一个程序通信时,先进行三次握手后,
在建立一个双方之间建立一个连接,所有数据就在这个连接中传递
每一次收到信息都会进行反馈,表示这个信息我收到了,
因此TCP是非常可靠的
连接断开需要四次挥手
//server-接收图片
public static void main(String[] args) throws IOException {
//绑定主机端口
ServerSocket server = new ServerSocket(9968);
// 监听客户端请求,获取Socket对象
Socket accept = server.accept();
// 获取输入流读取数据
InputStream in = accept.getInputStream();
File file = new File("D:\\jpg");
if (!file.exists()) {
file.mkdirs();
}
// 创建输出流写入数据
String filename = System.currentTimeMillis() + new Random().nextInt(100) + ".jpg";
FileOutputStream output = new FileOutputStream(file + File.separator + filename);
byte[] b = new byte[1024];
int len = 0;
while ((len = in.read(b)) > 0) {
output.write(b, 0, len);
}
// 向客户端发送数据
OutputStream out = accept.getOutputStream();
// 输出数据
out.write("上传成功! ".getBytes());
// 关闭资源
output.close();
out.close();
in.close();
accept.close();
server.close();
}
//client-上传图片
public static void main(String[] args) throws IOException {
// 绑定服务器的IP和端口,并发送连接到服务器获取Socket对象
Socket socket = new Socket("127.0.0.1", 9968);
// 获取输出流
OutputStream out = socket.getOutputStream();
FileInputStream fileIn = new FileInputStream("D:\\图片\\2.jpg");
byte[] b = new byte[1024];
int len = 0;
while ((len = fileIn.read(b)) > 0) {
out.write(b, 0, len);
}
// 给服务器一个终止序列,不然服务端的while的read方法会造成阻塞
socket.shutdownOutput();
// 获取输入流
InputStream in = socket.getInputStream();
// 读取反馈数据
byte[] by = new byte[1024];
int lens = in.read(by);// 读取的数据长度
System.out.println(new String(by, 0, lens));
// 关闭资源
fileIn.close();
in.close();
out.close();
socket.close();
}
服务端可以运用多线程接收请求
//线程类
public class TCPRunable implements Runnable {
private Socket accept;
public TCPRunable() {
super();
}
public TCPRunable(Socket accept) {
super();
this.accept = accept;
}
@Override
public void run() {
// 获取输入流读取数据
InputStream in;
try {
// 获取输入流读取数据
in = accept.getInputStream();
File file = new File("D:\\jpg");
if (!file.exists()) {
file.mkdirs();
}
// 创建输出流写入数据
String filename = System.currentTimeMillis() + new Random().nextInt(100) + ".jpg";
FileOutputStream output = new FileOutputStream(file + File.separator + filename);
byte[] b = new byte[1024];
int len = 0;
while ((len = in.read(b)) > 0) {
output.write(b, 0, len);
}
// 向客户端发送数据
OutputStream out = accept.getOutputStream();
// 输出数据
out.write("上传成功! ".getBytes());
// 关闭资源
output.close();
out.close();
in.close();
accept.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//server
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(9968);
while (true) {
// 监听客户端请求,获取客户端Socket对象
Socket accept = server.accept();
new Thread(new TCPRunable(accept)).start();
}
二者区别是:
1、连接方面区别
TCP面向连接
UDP是无连接的,即发送数据之前不需要建立连接。
2、安全方面的区别
TCP提供可靠的服务,通过TCP连接传送的数据,无差错,不丢失,不重复
UDP不保证数据可靠性,可能会造成数据出错。
3、传输效率的区别
TCP要保证数据可靠,所以传输效率相对较低。
UDP不保证数据可靠,所以传输效率高
浏览器请求充当客户端
用浏览器发送请求来充当客户端的请求
服务器接受请求,发送一个响应数据给浏览器
web开发中的请求与响应都是遵循了HTTP协议的格式
只要获悉了HTTP的请求与响应格式就获取到请求信息
设置响应数据
对后续的web开发很有帮助
public class HttpServer {
public static void main(String[] args) throws IOException {
//绑定本机3367端口
ServerSocket servers = new ServerSocket(3367);
// 监听客户端请求,获取客户端Socket连接对象
Socket accept = servers.accept();
// 获取连接对象的流对象
OutputStream out = accept.getOutputStream();
// 用流对象输出数据完成响应
out.write("HTTP\\1.1 200 OK\\r\\n\\r\\n hellowprld".getBytes());
//浏览器接收响应会根据响应行的代码来判断
//是不是符合http协议的响应
//响应行HTTP\\1.1 200 OK——协议/协议版本 状态码 状态描述信息
// 关闭资源
out.close();
accept.close();
//浏览器发送请求localhost:3367
}
}