导语
通过计算机网络可以使多台计算机实现连接,位于同一个网络的计算机 想要通信就要遵守一定的协议和规则,这就好比道路中行驶的汽车要遵守 交通规则一样,在计算机网络中这些连接和通信的规则称为网络通信协议 他对数据的传输格式,传输速率,传输步骤等做了统一规定,通信双方必须 同时遵守才能完成数据交换。
网络通信协议有很多种目前应用最广泛的是TCP/IP协议(传输控制协议/ 英特网互联协议),他是一个包含TCP协议和IP协议,UDP协议和其他一些 协议的协议组。
TCP/IP协议分层
在进行数据的传输时,为了保证发送的数据和接受的数据一致,这时就 需要在原有的数据上添加很多信息以保证数据在传输过程中数据格式完全 一致。TCP/IP协议的层次比较简单,共分为四层: 链路层:链路层是用来定义物理传输通道,通常是对某些网络连接设备 的驱动协议,例如针对光纤,网线提供的驱动。 网络层:网络层是整个TCP/IP协议的核心,它主要用于将传输的数据进行 分组,将分组数据发送到目标计算机或网络。 传输层:主要使网络程序进行通信,在进行网络通信时,可以采用TCP 协议也可以采用UDP协议。 应用层:主要负责应用程序的协议,例如HTTP协议,FTP协议等。
位于传输层的TCP协议和UDP协议
TCP协议
面向连接的协议,每次客户端和服务器进行连接时,会有"三次握手"来保证数据的安 全性。第一次握手客户端向服务端发送请求并等待确认,第二次握手服务器端向客户 端回应响应,通知客户端以接收到请求,第三次握手客户端再次向服务端发送消息确 认连接。
UDP协议
面向无连接的协议。 UDP协议传输效率高,不安全,容易丢包。 类似于发短信,发送前不关心对方是否能够接收。接收后也不会给发送者一个反馈。 一般用于对数据完整性要求不高的场景:视频聊天,直播,游戏 UDP在传输时会将数据进行分包处理,每一个包的大小不能超过64k。
使用UDP协议实现的网络聊天室
package com.jmy.tcpip;
import java.io.IOException;
import java.net.*;
import java.util.Scanner;
public class ChatDemo {
public static void main(String[] args) {
new Thread(new Sender()).start();
new Thread(new Receiver()).start();
}
}
class Sender implements Runnable {
private DatagramSocket ds;
@Override
public void run() {
try {
ds = new DatagramSocket();
} catch (SocketException e) {
e.printStackTrace();
}
// 创建装载消息的集装箱
DatagramPacket dp;
// 一直发送消息
while (true) {
String str = new Scanner(System.in).nextLine(); // 有阻塞作用
try {
/**
* Constructs a datagram packet for sending packets of length
* {@code length} to the specified port number on the specified
* host. The {@code length} argument must be less than or equal
* to {@code buf.length}.
*
* @param buf the packet data.
* @param length the packet length.
* @param address the destination address.
* @param port the destination port number.
* @see java.net.InetAddress
*/
dp = new DatagramPacket(str.getBytes(),str.getBytes().length,InetAddress.getByName("127.0.0.1"),);
//发送数据
ds.send(dp);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
class Receiver implements Runnable{
private DatagramSocket ds;
@Override
public void run() {
try {
ds = new DatagramSocket();
} catch (SocketException e) {
e.printStackTrace();
}
while (true) {
byte[] byt = new byte[ * ];
try {
/**
* Constructs a {@code DatagramPacket} for receiving packets of
* length {@code length}.
* <p>
* The {@code length} argument must be less than or equal to
* {@code buf.length}.
*
* @param buf buffer for holding the incoming datagram.
* @param length the number of bytes to read.
*/
DatagramPacket dp = new DatagramPacket(byt,byt.length);
ds.receive(dp);
// 解析数据
System.out.println(dp.getAddress() + ":" + dp.getPort() + "说" + new String(dp.getData()));
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
使用TCP协议完成文件上传
客户端
package com.jmy.tcpip;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
public class Client {
public static void main(String[] args) throws IOException {
// 创建套接字对象
Socket s = new Socket(InetAddress.getByName("127.0.0.1"),);
// 获取输出流将文件写出到服务端
OutputStream os = s.getOutputStream();
// 将文件写入到内存
File file = new File("C:\\Users\\Admin\\Desktop\\让Paxos更简单.txt");
String fileName = file.getName();
FileInputStream fis = new FileInputStream(file);
byte[] byt = new byte[ * ];
os.write(fileName.getBytes().length);
os.write(fileName.getBytes());
int len;
while ((len = fis.read(byt)) != -) {
os.write(byt,,len);
}
// 通知服务端上传完毕
s.shutdownOutput();
// 关流
fis.close();
os.close();
}
}
服务端
package com.jmy.tcpip;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket();
// 监听客户端套接字流
Socket s = ss.accept();
// 将客户端上传的文件读入到内存中
InputStream is = s.getInputStream();
byte i = (byte) is.read();
byte[] filenamebys = new byte[i];
is.read(filenamebys);
FileOutputStream fos = new FileOutputStream("D:/" + new String(filenamebys));
System.out.println(new String(filenamebys));
byte[] byt = new byte[ * ];
int len;
while ((len = is.read(byt)) != -) {
fos.write(byt,,len);
}
s.shutdownOutput();
fos.close();
s.close();
ss.close();
}
}