1、网络通信协议分类
-
TCP/IP是Internet最基本,最广泛的协议,在TCP协议中,客户端和服务器端有3次交互,以保证连接的可靠
- 第一次握手:客户端向服务器端发送请求连,等待服务器端确认。
- 第二次握手:服务器端向客户端回送一个响应,通知客户端收到了一个请求连接
- 第三次握手:客户端再次向服务器发送确认信息,确认连接
-
UDP(用户数据报协议:User Datagram Protocol),UDP是无连接通信协议,即在数据传输的时候数据的发送端和接受端不建立逻辑链接。简单的说,当一台计算机向另一台计算机发送数据时,发送端不会确认接收端是否存在就会发送数据,同样接收端接收到数据后也不会向发送端反馈接收到数据
UDP特点:耗资小,通信效率高,一般音频,视频传输都会用到UDP协议,比如视频会议,偶尔会丢失一俩个数据包,发送的数据会限制在64K以内。
2、网络编程三要素
- 协议
- IP地址
- 端口
3、TCP通信的概述
客户端和服务器端进行一次数据交互,需要4个IO对象,(字节流对象)
服务器端必须明确俩件事情
- 多个客户端同时和服务器进行交互,服务器必须明确和哪个进行交互,在服务器端有一个方法accept,获取到请求的客户端对象
- 多个客户端同时和服务器进行交互,需要使用多个IO流和客户端进行交互。服务器使用客户端的字节输入流读取客户端发送的数据,服务器使用客户端的字节输出流给客户端回写数据。
4、TCP客户端,服务器端实现
- 客户端
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class TCPClient {
/*
* TCP通信客户端:请求服务器向其发送数据,读取服务器返回的数据
* 表示客户端的类:java.net.Socket
*
* 成员方法:
* OutputStream getOutputStream(),返回此套接字的输出流
* InputStream getInputStream()
*
* 注意:
* 1、客户端和服务器进行交互,必须使用Socket中提供的网络流,不能使用自己创建的流对象
* 2、当客户端和服务器3次握手连接建立连接通路时,如果服务器没有启动会抛出异常
* */
public static void main(String[] args) throws IOException {
Socket socket = new Socket("127.0.0.1",9999);
//向服务器发送
OutputStream os = socket.getOutputStream();
os.write("Hello Server".getBytes());
InputStream is = socket.getInputStream();
byte[] bytes = new byte[1024];
int len = is.read(bytes);
System.out.println("读取到服务器会写数据:" + new String(bytes,0,len));
socket.close();
}
}
- 服务器端
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class TCPServer {
/*
* TCP通信的服务器端
* java.net.ServerSocket
* */
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(9999);
System.out.println("等待连接...");
//获取请求的客户端对象socket
Socket socket = server.accept();
InputStream is = socket.getInputStream();
//读取客户端的发送的数据
byte[] bytes = new byte[1024];
int len = is.read(bytes);
System.out.println("读取到客户端发送数据:" + new String(bytes,0,len));
//向客户端发送数据,(需要从获取的客户端的socket对象中获取流对象,而不能自己写流对象)
OutputStream os = socket.getOutputStream();
os.write("OK,Thanks".getBytes());
//释放资源
socket.close();
server.close();
}
}
5、TCP文件上传
注意:客户端和服务器在本地硬盘读写需要使用自己创建的字节流对象(本地流)
客户端和服务器之间的读写需要使用Socket中提供的字节流对象(网络流)
- TCP文件上传服务器端:
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class TCPFileServer {
public static void main(String[] args) throws IOException {
//创建服务器的ServerSocket对象
ServerSocket server = new ServerSocket(9898);
//获取请求客户端的socket对象
Socket socket = server.accept();
InputStream is = socket.getInputStream();
File file = new File("/Users/ydsungan/upload");
if(!file.exists()){
file.mkdirs();
}
//创建本地字节输出流
FileOutputStream fos = new FileOutputStream(file + "/test2.pdf");
int len = 0;
byte[] bytes = new byte[1024];
while((len = is.read(bytes))!=-1){
fos.write(bytes,0,len);
}
socket.getOutputStream().write("上传成功".getBytes());
fos.close();
socket.close();
server.close();
}
}
- 文件上传客户端
import java.io.*;
import java.net.Socket;
public class TCPFileClient {
public static void main(String[] args) throws IOException {
//创建本地字节输入流
FileInputStream fis = new FileInputStream("/Users/ydsungan/Documents/文档/test.pdf");
//创建客户端的socket对象
Socket socket = new Socket("127.0.0.1",9898);
OutputStream os = socket.getOutputStream();
//读取本地文件
int len = 0;
byte[] bytes = new byte[1024];
while((len = fis.read(bytes))!=-1){
os.write(bytes,0,len);
}
//给服务器写一个终止符
socket.shutdownOutput();
InputStream is = socket.getInputStream();
while((len = is.read(bytes))!=-1){
System.out.println(new String(bytes,0,len));
}
fis.close();
socket.close();
}
}