前置知识:IO流 – 字节流和字符流的区别和使用,分别实现文本的复制
引言:
生活中的每个人都在进行网络通信(只要你不是八九十岁的老大爷老大妈,甚至有的老大妈大
爷比年轻人玩的还 6)。我们每天用的 QQ、微信 、and so on …实际上都是网络通信。
网络编程:
上图展现的就是一个简单的网络通信, 计算机 A 通过协议和传输到网络,网络再通过协议传输给另一个计算机。那什么是协议呢?
协议:为了让网络中不同计算机之间能够相互通信而建立的规则、约定、约定。
常见的协议有:
TCP协议:面向连接的、可靠的(不丢失、不重复、有序)、基于字节流的传输通信协议。
UDP协议:无连接的协议,在传输协议之前,客户端和服务端之间不建立和维护连接。提供不可靠的数据传输。
ip地址:网络上的唯一标识。(就像我们的家庭地址一样)。
ip的组成: 32 位,由 4 个 8 位 2 进制组成。(每一位最大值是 255,每一位十进制表示 0 ~ 255)
二进制不容易记忆,所以改成 了十进制。
socket(套接字): 基于 TCP 协议的网络通信,可以提供双向安全连接的网络通信,
socket 需要借助数据流(字节流) 来完成数据的传递工作。
实现C/S通信的简单步骤:
1、建立连接(服务端准备服务,开放端口,客户端根据 ip 地址和端口号 找到 对应的计算机进行连接)
2、通过 socket 生成 inputStream/outputStream(准备发送数据)
3、通过 inputStream/outputStream 进行发送、接受数据
4、关闭相应的流
TCP 实现通信:
Server.java --服务端
package cs;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) {
Socket socket = null;
InputStream in = null;
OutputStream out = null;
BufferedReader reader = null;
try {
// 准备服务(ip,端口),通过 serverSocket 产生服务端
ServerSocket serverSocket = new ServerSocket(8888);
System.out.println("服务端已连接");
// 相当于是一个监听器,监听客户端的连接,只有监听到连接后 才会向下走
socket = serverSocket.accept();
System.out.println("连接成功。。。。。。。。。。。。。");
// 通过 socket 只能得到字节流,要想用其他的流就需要进行转换
// 现在接受信息,就是输入流(注意参照物)
in = socket.getInputStream();
// 将字节流转换为字符流,因为传过来的是字符,字符流在转化成缓存流(就不用再自己去弄缓存区了)
reader = new BufferedReader(new InputStreamReader(in));
// 存储信息
String info = null;
// 客户端发送的信息可能有多条,逐行读取
while ((info = reader.readLine()) != null) {
System.out.println("I am server,接受到客户端的信息是 :" + info);
}
// 将管道中的内容拿出来,不拿出来就还在管道中(输入流管道)
socket.shutdownInput();
// 反馈给客户端
out = socket.getOutputStream();
// 因为 out 是 字节流产生的对象,所以需要通过字节的方式进行传输
out.write("Hello client,已经接受到你的消息!".getBytes());
// 将管道中的内容拿出来(输出流管道)
socket.shutdownOutput();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
// 关闭各个流和套接字
if (socket != null) socket.close();
if (reader != null) reader.close();
if (in != null) in.close();
if (out != null) out.close();
} catch (IOException E) {
E.printStackTrace();
}
}
}
}
Client.java – 客户端
package cs;
import java.io.*;
import java.net.Socket;
public class Client {
public static void main(String[] args) {
Socket socket = null;
OutputStream out = null;
InputStream in = null;
BufferedReader reader = null;
try {
// 根据 ip 地址 和端口号建立连接
socket = new Socket("127.0.0.1", 8888);
// 输出流,向外发出信息
out = socket.getOutputStream();
// 通过字节的方式
out.write("Hello Server".getBytes());
// 将管道中的内容拿出来,不拿出来就还在管道中
socket.shutdownOutput();
// 输入流(服务端的信息输入到客户端)
in = socket.getInputStream();
// 字符转换流 --> 字符缓存流
reader = new BufferedReader(new InputStreamReader(in));
String info = null;
while ((info = reader.readLine()) != null) {
System.out.println(info);
}
socket.shutdownInput();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (socket != null) socket.close();
if (reader != null) reader.close();
if (in != null) in.close();
if (out != null) out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
效果图:
当只启动服务端时,由于没有客户端建立连接,所以服务端 serverSocket.accept(); 没有检测到有客户端连接,所以不会向下走:
当启动 客户端后:
后记:
到此,一个简单的网络通信就基本完成了,网络编程是一项大的内容,在Java 的学习过程中,只是简单的一部分,在上述代码的实现过程中,还用到了 IO 中的核心思想 – 装饰模式,有兴趣的小伙伴可以了解一下,由于博主能力有限,大家可以尝试着进行改进,实现聊天通讯,实现客户端和服务端的交互。相信有了上面的基础实现这个功能应该不难,后续我也会更新上。
有问题的小伙伴欢迎在下方留言。
如果感觉对您有帮助,别忘了点个小赞哦,嘻嘻,关注一下也是可以的,加油!!