软件结构 & 网络通信协议
B/S结构: Browser/Server结构, 是指浏览器和服务器结构, 常见的程序有 Google, Firefox 等
两种结构各有优势, 都离不开网络的支持, 网络编程, 就是在一定协议下, 实现两台计算机的通信的程序.
TCP协议
面向连接的通信, 客户端和服务端必须经过3次握手, 建立逻辑连接, 才能通信
通信的步骤:
-
-
客户端请求服务端, 建立逻辑连接 (IO对象 socket)
-
客户端和服务端之间通过 socket 进行通信
服务端是没有 IO 对象的, 它可以获取到客户端的 socket, 来和每个客户端通信
Serversocket
public ServerSocket(int port): 创建绑定到指定端口号的服务器套接字
-
public Socket accept(): 侦听并返回客户端的套接字, 然后使用客户端的套接字与客户端进行交互
-
public void close(): 关闭套接字, 释放资源
套接字是包含了 IP 地址和端口号的网络单位
Socket(String host, int port): 创建一个流套接字, 并将其连接到指定主机, 指定端口
-
OutputStream getOutputStream(): 返回套接字的输出流
-
InputStream getInputStream(): 返回套接字的输入流
-
void close(): 关闭此套接字
server
import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; public class TCPServer { public static void main(String[] args) throws IOException { // 创建 server socket ServerSocket server = new ServerSocket(9000); // 获取客户端连接 Socket socket = server.accept(); // 获取输入 IO流对象 InputStream is = socket.getInputStream(); // 读取 数据 byte[] bytes = new byte[1024]; int dataLen = is.read(bytes); System.out.println("来自客户端的消息: " + new String(bytes, 0, dataLen)); // 发送数据 OutputStream os = socket.getOutputStream(); os.write("收到了".getBytes("UTF-8")); os.flush(); //释放资源 socket.close(); server.close(); } }
client
import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; public class TCPClient { public static void main(String[] args) throws IOException { // 创建 socket, 这里就连接服务器的地址和端口了 Socket socket = new Socket("localhost", 9000); // 获取输出 IO流 对象 OutputStream os = socket.getOutputStream(); // 写入 IO 流, 发送到服务端 os.write("hello world".getBytes("UTF-8")); os.flush(); System.out.println("信息发送成功"); //接收服务端的信息 InputStream is = socket.getInputStream(); byte[] bytes = new byte[1024]; int dataLen = is.read(bytes); System.out.println("来自服务端的响应: " + new String(bytes, 0, dataLen)); //释放资源 socket.close(); } }
把桌面上的文件由客户端传给服务端, 然后服务端改个名字保存到桌面
server
import java.io.*; import java.net.ServerSocket; import java.net.Socket; public class TCPServer { public static void main(String[] args) throws IOException { // 创建 server socket ServerSocket server = new ServerSocket(9000); // 获取客户端连接 Socket socket = server.accept(); // 获取输入 IO流对象 InputStream is = socket.getInputStream(); // 创建文件 IO输出流, 写到本地 File f = new File("C:\Users\chenkai\Desktop"); FileOutputStream fos = new FileOutputStream(f.getAbsoluteFile() + "\test2.jpg"); // 读取 socket 数据, 写到文件输入流 int len = 0; byte[] bytes = new byte[1024]; while ((len = is.read(bytes))!=-1){ fos.write(bytes, 0, len); } // 文件写入完成, 告诉客户端 OutputStream os = socket.getOutputStream(); os.write("文件上传完成".getBytes("UTF-8")); System.out.println("文件写入完成"); //释放资源 fos.close(); socket.close(); server.close(); } }
client
import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; public class TCPClient { public static void main(String[] args) throws IOException, IOException { // 创建 socket, 这里就连接服务器的地址和端口了 Socket socket = new Socket("localhost", 9000); // 获取输出 IO流 对象 OutputStream os = socket.getOutputStream(); // 获取文件输入流 FileInputStream fis = new FileInputStream("C:\Users\chenkai\Desktop\test.jpg"); // int len = 0; byte[] bytes = new byte[1024]; while ((len = fis.read(bytes)) != -1) { // 写入 IO 流, 发送到服务端 os.write(bytes); } // 告诉服务端, 文件写入完成 socket.shutdownOutput(); System.out.println("文件上传完成"); //接收服务端的信息 InputStream is = socket.getInputStream(); while ((len = is.read(bytes)) != -1) { System.out.println("来自服务端的响应: " + new String(bytes,0,len, "UTF-8")); } //释放资源 fis.close(); socket.close(); } }
浏览器向TCP服务器发送请求, 服务器返回一张图片给浏览器
import java.io.*; import java.net.ServerSocket; import java.net.Socket; public class HTTPServer { public static void main(String[] args) throws IOException { // 创建 server socket ServerSocket server = new ServerSocket(9000); while(true) { // 获取客户端连接 Socket socket = server.accept(); // 获取输入 IO流对象 InputStream is = socket.getInputStream(); // 读取 socket 数据 // int len = 0; // byte[] bytes = new byte[1024]; // while ((len = is.read(bytes))!=-1){ // System.out.println(new String(bytes, 0, len)); // } BufferedReader br = new BufferedReader(new InputStreamReader(is)); String firstLine = br.readLine(); String fileName = firstLine.split(" ")[1].substring(1); System.out.println("C:\" + fileName.replace("/", "\")); fileName = "C:\" + fileName.replace("/", "\"); // 读取本地文件 // FileInputStream fis = new FileInputStream("C:\Users\chenkai\Desktop\test.jpg"); FileInputStream fis = new FileInputStream(fileName); // 将一张图片回写给浏览器 OutputStream os = socket.getOutputStream(); os.write("HTTP/1.1 200 OK ".getBytes("UTF-8")); os.write("Content-Type: image/jpg ".getBytes("UTF-8")); os.write(" ".getBytes("UTF-8")); // int len = 0; byte[] bytes = new byte[1024]; while ((len = fis.read(bytes)) != -1) { os.write(bytes, 0, len); } //释放资源 br.close(); fis.close(); socket.close(); } //server.close(); } }
ending ~