01. 软件介绍
C/S结构 :全称为Client/Server结构,是指客户端和服务器结构。常见程序有QQ、迅雷等软件。文章源自JAVA秀-https://www.javaxiu.com/740.html
B/S结构 :全称为Browser/Server结构,是指浏览器和服务器结构。文章源自JAVA秀-https://www.javaxiu.com/740.html
02. 协议的介绍
参考 Java基础学习20:【网络编程】中的图。文章源自JAVA秀-https://www.javaxiu.com/740.html
03. TCP的三次握手
参考 Java基础学习20:【网络编程】中的图。文章源自JAVA秀-https://www.javaxiu.com/740.html
04. IP的介绍
IP是在网络中对于计算机的唯一标识文章源自JAVA秀-https://www.javaxiu.com/740.html
05. 端口号的介绍
端口号是在计算机中,对于应用设备的唯一标识。文章源自JAVA秀-https://www.javaxiu.com/740.html
06. 客户端和服务器的介绍
参考 Java基础学习20:【网络编程】中的图。文章源自JAVA秀-https://www.javaxiu.com/740.html
07. TCP中的IO流技术
参考 Java基础学习20:【网络编程】中的图。文章源自JAVA秀-https://www.javaxiu.com/740.html
08. TCP的客户端的实现
/*
TCP的客户端(TCP通信的两边分别是客户端和服务器)
在Java中,有一个类叫做Socket,这个类就表示TCP通信的客户端。
Socket的构造方法:
Socket(String host, int port):参数host表示目标服务器的ip地址。 参数port表示目标服务器程序的端口号
Socket的其他方法:
OutputStream getOutputStream(): 用于获取输出流对象, 该输出流用于向目的地写(发送)数据。
InputStream getInputStream(): 用于获取输入流对象, 该输入流用于读取(接收)目的地程序发送过来的数据。
void close(): 释放资源
TCP客户端的实现步骤:
1. 创建Socket对象,表示客户端。
2. 通过Socket对象调用getOutputStream获取一个输出流,用来发送数据。
3. 通过输出流向服务器发送(写)数据
4. 通过Socket对象调用getInputStream获取一个输入流, 用来接收数据。
5. 通过输入流接收服务器发送过来的数据。
6. 释放资源。
*/
public class Demo01Client {
public static void main(String[] args) throws IOException {
//1. 创建Socket对象,表示客户端。
//创建Socket对象的时候,会主动连接服务器,如果无法连接,那么就会报错(三次握手就是在这完成的)
Socket socket = new Socket("127.0.0.1", 9527);
//2. 通过Socket对象调用getOutputStream获取一个输出流,用来发送数据。
OutputStream out = socket.getOutputStream(); //该输出流的目的地是服务器。
//3. 通过输出流向服务器发送(写)数据
out.write("你好服务器, I'm coming".getBytes());
//4. 通过Socket对象调用getInputStream获取一个输入流, 用来接收数据。
InputStream in = socket.getInputStream(); //该输入流的数据源来自服务器,这个流用于读取服务器发过来的数据。
//5. 通过输入流接收(读取)服务器发送过来的数据。
byte[] bArr = new byte[1024];
int len = in.read(bArr);
System.out.println(new String(bArr, 0, len));//将读取到的数据转成字符串进行打印
//6. 释放资源。
socket.close();
}
}
09. TCP的服务器的实现
/*
TCP的服务器端。
在Java中,有一个类可以表示TCP的服务器端,这个类叫做ServerSocket
ServerSocket的构造方法:
ServerSocket(int port): 参数要传递一个端口号。 这个端口号表示该服务器程序的端口号。
ServerSocket的其他方法:
Socket accept(): 监听并获取客户端Socket
TCP服务器端的实现步骤:
1. 创建ServerSocket表示服务器。
2. 调用服务器ServerSocket的accept方法,监听并获取客户端请求。
3. 通过监听获取到的客户端Socket获取输入流,用来读取。
4. 通过得到的数据读取客户端发送过来的数据。
5. 通过监听获取到的客户端Socket获取输出流, 用来发送数据。
6. 通过输出流给客户端发送数据。
7. 释放资源。
*/
public class Demo02Server {
public static void main(String[] args) throws IOException {
//1. 创建ServerSocket表示服务器。
ServerSocket serverSocket = new ServerSocket(9527);
//2. 调用服务器ServerSocket的accept方法,监听并获取客户端请求。
Socket socket = serverSocket.accept();
//3. 通过监听获取到的客户端Socket获取输入流,用来读取。
InputStream in = socket.getInputStream();//得到的输入流,用来接收客户端发送过来的数据。
//4. 通过得到的数据读取客户端发送过来的数据。
byte[] bArr = new byte[1024];
int len = in.read(bArr);
System.out.println(new String(bArr, 0, len));
//5. 通过监听获取到的客户端Socket获取输出流, 用来发送数据。
OutputStream out = socket.getOutputStream(); //得到的输出流,用来向客户端写数据。
//6. 通过输出流给客户端发送数据。
out.write("收到了你的消息,谢谢".getBytes());
//7. 释放资源。
socket.close();
serverSocket.close();
}
}
10. TCP案例的流程
参考 Java基础学习20:【网络编程】中的图。文章源自JAVA秀-https://www.javaxiu.com/740.html
11. 文件上传的流程说明
参考 Java基础学习20:【网络编程】中的图。文章源自JAVA秀-https://www.javaxiu.com/740.html
12. 文件上传客户端的操作
/*
文件上传的客户端。
对于客户端来说,他要做事情是读取自己电脑上的文件, 将读取到的文件中的字节发送给服务器。 然后再接收服务器返回过来的数据。
客户端的实现步骤:
1. 创建客户端Socket对象。
2. 创建一个FileInputStream,用于读取自己电脑上的文件
3. 调用Socket的getOutputStream,获取一个输出流, 用来向服务器写数据。
4. 开始读写,读取客户端自己电脑的文件, 每读取一次,就将读取到的内容发送给服务器。
5. 释放资源。
6. 调用Socket的getInputStream,获取一个输入流, 用来接收服务器发送过来的数据。
7. 调用输入流的read方法,接收数据。
8. 释放资源。
*/
public class Demo01Client {
public static void main(String[] args) throws IOException {
//1. 创建客户端Socket对象。
Socket socket = new Socket("127.0.0.1", 9527);
//2. 创建一个FileInputStream,用于读取自己电脑上的文件
FileInputStream fis = new FileInputStream("d:\\client\\aa.jpg");
//3. 调用Socket的getOutputStream,获取一个输出流, 用来向服务器写数据。
OutputStream out = socket.getOutputStream();
//4. 开始读写,读取客户端自己电脑的文件, 每读取一次,就将读取到的内容发送给服务器。
byte[] bArr = new byte[1024];
int len;
while((len = fis.read(bArr)) != -1) {
//将读取到的数据发送给服务器
out.write(bArr, 0, len);
}
//通知服务器,以后再也不会给服务器写数据了.
socket.shutdownOutput();
//5. 释放资源。
fis.close();
//6. 调用Socket的getInputStream,获取一个输入流, 用来接收服务器发送过来的数据。
InputStream in = socket.getInputStream();
//7. 调用输入流的read方法,接收数据。
len = in.read(bArr);
System.out.println(new String(bArr, 0, len));
//8. 释放资源。
socket.close();
}
}
13. 文件上传服务器的实现
/*
上传案例的服务器端。
对于服务器来说, 服务器要做的事情是接收客户端发送过来的数据, 并将这些数据写到自己的电脑。 然后再给客户端回复一个消息。
上传案例服务器的实现:
1. 创建ServerSocket表示服务器。
2. 监听并获取客户端的Socket
3. 通过Socket获取一个输入流,用来读取客户端发送过来的数据。
4. 自己创建一个输出流, 用来向服务器自己的电脑写数据。
5. 开始读写, 每从客户端读取一次数据,那么就将读取到的数据写到自己电脑。
6. 释放资源。
7. 通过Socket获取一个输出流, 用来向客户端发送数据。
8. 通过输出流调用write方法,发送数据。
9. 释放资源。
*/
public class Demo02Server {
public static void main(String[] args) throws IOException {
//1. 创建ServerSocket表示服务器。
ServerSocket serverSocket = new ServerSocket(9527);
//2. 监听并获取客户端的Socket
Socket socket = serverSocket.accept();
//3. 通过Socket获取一个输入流,用来读取客户端发送过来的数据。
InputStream in = socket.getInputStream();
//4. 自己创建一个输出流, 用来向服务器自己的电脑写数据。
//FileOutputStream fos = new FileOutputStream("d:\\server\\aa.jpg");
//FileOutputStream fos = new FileOutputStream("d:\\server\\" + System.currentTimeMillis() + ".jpg");
//使用UUID这个工具类可以获取一个随机的字符串序列(唯一)。
// UUID.randomUUID()该方法可以得到一个随机字符串序列,它的结果是UUID类型,再调用toString方法转成字符串
FileOutputStream fos = new FileOutputStream("d:\\server\\" + UUID.randomUUID().toString() + ".jpg");
//5. 开始读写, 每从客户端读取一次数据,那么就将读取到的数据写到自己电脑。
byte[] bArr = new byte[1024];
int len;
while((len = in.read(bArr)) != -1) {
//将读取到的数据写到服务器自己电脑
fos.write(bArr, 0, len);
}
//6. 释放资源。
fos.close();
//7. 通过Socket获取一个输出流, 用来向客户端发送数据。
OutputStream out = socket.getOutputStream();
//8. 通过输出流调用write方法,发送数据。
out.write("上传成功".getBytes());
//9. 释放资源。
socket.close();
serverSocket.close();
}
}
14. 文件上传案例中的问题以及解决方式
参考 Java基础学习20:【网络编程】中的图。文章源自JAVA秀-https://www.javaxiu.com/740.html
15. 上传案例服务器死循环的实现
/*
之前上传服务器: 服务器接收一个客户端的上传请求后,服务器就会停止,此时该服务器只能给一个客户端执行上传任务。
要实现的效果: 服务器可以给多个客户端执行上传操作, 每次给客户端执行上传操作后, 那么服务器也不会停止。
实现方式: 使用死循环。 使用死循环一直让服务器监听客户端的请求, 每监听到客户端的请求,那么就执行上传任务。
*/
"all") //抑制警告
(public class Demo03DeadLoopServer {
public static void main(String[] args) throws IOException {
//1. 创建ServerSocket表示服务器。
ServerSocket serverSocket = new ServerSocket(9527);
//在死循环中一直监听客户端请求, 一直执行上传任务。
while (true) {
//2. 监听并获取客户端的Socket
Socket socket = serverSocket.accept();
//3. 通过Socket获取一个输入流,用来读取客户端发送过来的数据。
InputStream in = socket.getInputStream();
//4. 自己创建一个输出流, 用来向服务器自己的电脑写数据。
FileOutputStream fos = new FileOutputStream("d:\\server\\" + UUID.randomUUID().toString() + ".jpg");
//5. 开始读写, 每从客户端读取一次数据,那么就将读取到的数据写到自己电脑。
byte[] bArr = new byte[1024];
int len;
while((len = in.read(bArr)) != -1) {
//将读取到的数据写到服务器自己电脑
fos.write(bArr, 0, len);
}
//6. 释放资源。
fos.close();
//7. 通过Socket获取一个输出流, 用来向客户端发送数据。
OutputStream out = socket.getOutputStream();
//8. 通过输出流调用write方法,发送数据。
out.write("上传成功".getBytes());
//9. 释放资源。
socket.close();
}
}
}
16. 上传案例多线程版本的实现
/*
死循环版本服务器存在的问题: 如果有一个客户端上传了一个非常大的文件, 那么其他过来请求的客户端只能等着。
问题原因: 在整个代码中只有一个main线程在执行任务。 服务器会使用main线程监听客户端请求, 再使用main线程执行上传任务,
main线程的上传任务没有执行完, 那么就无法开始下次循环,去监听下一个客户端请求。
解决方式: 使用多线程, 让main线程监听客户端请求, 每监听到客户端请求,就表示有客户端要执行上传任务,那么我们创建新的线程,
使用新的线程去执行上传任务, 于此同时main线程还可以往下执行,再次去监听后面的客户端请求。
*/
"all") //抑制警告
(public class Demo04ThreadServer {
public static void main(String[] args) throws IOException {
//1. 创建ServerSocket表示服务器。
ServerSocket serverSocket = new ServerSocket(9527);
//在死循环中一直监听客户端请求, 一直执行上传任务。
while (true) {
//2. 监听并获取客户端的Socket
Socket socket = serverSocket.accept();
//当监听到客户端请求后,创建一个新的线程,使用新的线程执行上传任务。
new Thread(() -> {
//ctrl + alt + t可以生成try...catch
try {
//3. 通过Socket获取一个输入流,用来读取客户端发送过来的数据。
InputStream in = socket.getInputStream();
//4. 自己创建一个输出流, 用来向服务器自己的电脑写数据。
FileOutputStream fos = new FileOutputStream("d:\\server\\" + UUID.randomUUID().toString() + ".jpg");
//5. 开始读写, 每从客户端读取一次数据,那么就将读取到的数据写到自己电脑。
byte[] bArr = new byte[1024];
int len;
while((len = in.read(bArr)) != -1) {
//将读取到的数据写到服务器自己电脑
fos.write(bArr, 0, len);
}
//6. 释放资源。
fos.close();
//7. 通过Socket获取一个输出流, 用来向客户端发送数据。
OutputStream out = socket.getOutputStream();
//8. 通过输出流调用write方法,发送数据。
out.write("上传成功".getBytes());
//9. 释放资源。
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}).start();
}
}
}
/*
浏览器也可以当做客户端。 B/S:就是浏览器/服务器的程序。
服务器收到客户端的请求后, 要给客户端(浏览器)回一个html文件的内容,那么浏览器才能够看到页面。
*/
public class Demo01Server {
public static void main(String[] args) throws IOException {
//创建一个ServerSocket表示服务器
ServerSocket serverSocket = new ServerSocket(10086);
while(true) {
//使用服务器调用accept方法监听并获取客户端请求
Socket socket = serverSocket.accept();
//如果监听到了客户端的请求, 那么就给客户端(浏览器)回写数据
new Thread(() -> {
try {
//通过Socket获取一个输出流,用来给浏览器写数据
OutputStream out = socket.getOutputStream();
//创建输入流,用来读取自己电脑的index.html文件的内容。
FileInputStream fis = new FileInputStream("day12\\index.html");
//B/S(浏览器/服务器)现在采用的协议是http协议。
//根据http协议的要求, 必须先给浏览器写三个固定的内容(前三行固定)
out.write("HTTP/1.1 200 OK\r\n".getBytes());//第一行
out.write("Content-Type=html/text\r\n".getBytes()); //第二行
out.write("\r\n".getBytes()); //第三行. 第三行固定是一个空换行。
//开始读取html文件,并写给浏览器
byte[] bArr = new byte[1024];
int len;
while((len = fis.read(bArr)) != -1) {
out.write(bArr, 0, len);
}
//释放资源
fis.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}).start();
}
}
}
文章源自JAVA秀-https://www.javaxiu.com/740.html
评论