网络编程(3)TCP通信协议
TCP通信协议
1️⃣TCP通信原理:
TCP
通信协议是一种可靠的网络协议,它在通信的两端各建立一个Socket
对象。- 通信之前要保证连接已经建立,否则报错
- 通过
Socket
产生IO
流来进行网络通信
2️⃣TCP发送数据的步骤:
- 创建客户端的
Socket
对象与指定服务端连接---》Socket(String host,int port)
- 获取输出流,写数据---》
OutputStream getOutputStream()
- 释放资源---》
void close()
客户端代码演示:
import java.io.IOException;
import java.io.OutputStream;
import java.net.*;
import java.util.Scanner;
public class ClientDemo{
public static void main(String[] args) throws IOException {
Socket socket = new Socket("127.0.0.1", 10000);
OutputStream os = socket.getOutputStream();
os.write("数据".getBytes());
os.close();
socket.close();
}
}
3️⃣TCP接收数据的步骤:
- 创建服务器端的
Socket
对象(ServerSocket
)---->ServerSocket(int port)
- 监听客户端连接,返回一个
Socket
对象 ----》Socket accept()
- 获取输入流,读数据,并把数据显示在控制台---》
InputStream getInputStream()
- 释放资源
void close()
服务器端的代码演示:
import java.io.IOException;
import java.io.InputStream;
import java.net.*;
public class ServerDemo {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(10000);
Socket accept = serverSocket.accept();
InputStream is = accept.getInputStream();
int b;
while((b=is.read())!=-1){
System.out.println((char)b);
}
is.close();
serverSocket.close();
}
}
先运行服务器端,再运行客户端,运行结果如下:
出现乱码的原因是,使用了字节流,当使用(char
)进行对带有占2个字节的中文的数据进行强转换时,发送了错误。使用字符流可以解决这个问题。
4️⃣原理剖析:
accept
方法是阻塞的,作用是等待客户端连接- 客户端创建对象并连接服务器,此时是通过三次握手协议保证跟服务器之间的连接
- 针对客户端来讲,是往外写,所以是输出流,针对服务器来讲,是输入流
read
方法也是阻塞的,会一直保持读取的状态,直到读到结束标记- 在关闭流的时候,还多了一个往服务器写结束标记的动作
- 最后一步断开连接,是通过四次挥手协议保证连接终止
5️⃣三次握手
6️⃣四次挥手
7️⃣TCP通信程序练习1
练习要求:
- 客户端:发送数据,接收服务器反馈
- 服务端:接收数据,给出反馈
客户端代码:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.*;
public class ClientDemo{
public static void main(String[] args) throws IOException {
Socket socket = new Socket("127.0.0.1", 10000);
OutputStream os = socket.getOutputStream();
os.write("hello".getBytes());
socket.shutdownOutput(); //仅仅关闭输出流,不影响Socket
BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line;
while((line=br.readLine())!=null){
System.out.println(line);
}
os.close();
socket.close();
}
}
服务器端的代码:
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.net.*;
public class ServerDemo {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(10000);
Socket accept = serverSocket.accept();
InputStream is = accept.getInputStream();
int b;
while((b=is.read())!=-1){
System.out.println((char)b);
}
BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(accept.getOutputStream()));
bw.write("你谁啊?");
bw.flush();
bw.close();
is.close();
accept.close();
serverSocket.close();
}
}
先运行服务端,再运行客户端,运行结果如下:
可以看到,客户端收到了服务端的反馈,而且通过转换流解决了中文发送的问题。
8️⃣TCP练习2
练习要求:文件上传
- 【客户端】输入流,从硬盘读取文件数据到程序中。
- 【客户端】输出流,写出文件数据到服务端。
- 【服务端】输入流,读取文件数据到服务端程序。
- 【服务端】输出流,写出文件数据到服务器硬盘中。
客户端代码:
public class FileUPload_Client {
public static void main(String[] args) throws IOException {
// 1.创建流对象
// 1.1 创建输入流,读取本地文件
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("test.jpg"));
// 1.2 创建输出流,写到服务端
Socket socket = new Socket("localhost", 6666);
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
//2.写出数据.
byte[] b = new byte[1024 * 8 ];
int len ;
while (( len = bis.read(b))!=-1) {
bos.write(b, 0, len);
bos.flush();
}
System.out.println("文件发送完毕");
// 3.释放资源
bos.close();
socket.close();
bis.close();
System.out.println("文件上传完毕 ");
}
}
服务端代码:
public class FileUpload_Server {
public static void main(String[] args) throws IOException {
System.out.println("服务器 启动..... ");
// 1. 创建服务端ServerSocket
ServerSocket serverSocket = new ServerSocket(6666);
// 2. 建立连接
Socket accept = serverSocket.accept();
// 3. 创建流对象
// 3.1 获取输入流,读取文件数据
BufferedInputStream bis = new BufferedInputStream(accept.getInputStream());
// 3.2 创建输出流,保存到本地 .
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy.jpg"));
// 4. 读写数据
byte[] b = new byte[1024 * 8];
int len;
while ((len = bis.read(b)) != -1) {
bos.write(b, 0, len);
}
//5. 关闭 资源
bos.close();
bis.close();
accept.close();
System.out.println("文件上传已保存");
}
}