最近学到了网络编程,有个练习:
模拟BS服务器
模拟网站服务器,使用浏览器访问自己编写的服务端程序,查看网页效果。
踩了两个坑,就是:
①HTTPS,不能用这个协议,来访问,因为这玩意是加密了的,一开始我还以为它传的不是UTF-8,因为我用的IDEA,默认UTF-8,我还用InputStreamReader去转换,但是发现没法,后来,突然想起了,HTTPS是加密的,然后用HTTP试了,就可以了。
②网站输入的地址,可以用绝对路径,也可用相对路径,相对路径是相对于我们写的服务端类的项目位置比如我的服务端: 我们的地址就要这样输入:
http://localhost:8888/Advanced/src/Net/BSTCP/web/index.html
注意事项:
①这个是HTTP的响应头是固定的格式,需要注意:
Http响应头要固定:
②谷歌看不了,建议换其他浏览器看。
// 写入HTTP协议响应头,固定写法
os.write("HTTP/1.1 200 OK\r\n".getBytes());
os.write("Content‐Type:text/html\r\n".getBytes());
// 必须要写入空行,否则浏览器不解析
os.write("\r\n".getBytes());
写代码思路
客户端是网站,我们只写服务端
需要写两个服务端,一个是向客户端发送html代码,一个是发送图片
建立连接时,需要使用HTTP协议,而不能使用HTTPS协议,这个协议被加密了,所以客户端只能输出加密的请求头。
服务端的执行步骤:
先创建ServerSocket,监听请求,接收到了,就使用accept( )捕获。
利用网络输入流,读取客户端请求头,然后获取Get请求,其中的文件地址。
处理地址格式
使用本地文件流,读取文件,并向客户端输出
在创建一个传输照片的服务端,与传输html的服务端代码几乎一样,差别在于,传输照片服务端,要一直监听请求,因为他传输的不是一张照片
优化:
使用多线程,加快传输效率
下面放出全部代码:
html服务端:
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
//http://localhost:8888/Advanced/src/Net/BSTCP/web/index.html HTTP/1.1
//不能使用https,加密协议
public class Server {
public static void main(String[] args) throws IOException {
System.out.println("服务端启动,等待连接。。。。");
//创建一个服务器ServerSocket,和系统要指定的端口号
ServerSocket server = new ServerSocket(8888);
//使用accept方法获取到请求的客户端对象(浏览器)
Socket socket = server.accept();
//使用Socket对象中的方法getInputStream,获取到网络字节输入流InputStream对象
InputStream is = socket.getInputStream();
//输出客户端的请求
/*byte[] bytes = new byte[1024];
int len = is.read(bytes);
System.out.println(new String(bytes,0,len));
System.out.println("cao");*/
//把is字节流,转换成字符流,并且使用缓冲流读取
BufferedReader br = new BufferedReader(new InputStreamReader(is));
//读取第一行GET请求的内容
String s = br.readLine();
//按空格把它分开
String[] s1 = s.split(" ");
//把前面的"/"给排除,使用字符串的截取
String path = s1[1].substring(1);
System.out.println(path);
//创建一个fis流,读取本地的index.html文件
FileInputStream fis = new FileInputStream(path);
//获取网络输出流OutputStream,向客户端输出页面
OutputStream os = socket.getOutputStream();
// 写入HTTP协议响应头,固定写法
os.write("HTTP/1.1 200 OK\r\n".getBytes());
os.write("Content‐Type:text/html\r\n".getBytes());
// 必须要写入空行,否则浏览器不解析
os.write("\r\n".getBytes());
//向客户端输出
byte bytes[] = new byte[1024];
int len = 0;
while((len = fis.read(bytes))!=-1){
os.write(bytes);
}
//关闭资源
fis.close();
br.close();
socket.close();
}
}
照片服务端
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class ImageServer {
public static void main(String[] args) throws IOException {
System.out.println("服务端启动,等待连接。。。。");
//创建一个服务器ServerSocket,和系统要指定的端口号
ServerSocket server = new ServerSocket(8888);
while (true){
//使用accept方法获取到请求的客户端对象(浏览器)
Socket socket = server.accept();
//使用Socket对象中的方法getInputStream,获取到网络字节输入流InputStream对象
InputStream is = socket.getInputStream();
//输出客户端的请求
/*byte[] bytes = new byte[1024];
int len = is.read(bytes);
System.out.println(new String(bytes,0,len));
System.out.println("cao");*/
//多线程,加快传输速度
new Thread(new Runnable() {
@Override
public void run() {
try{
//把is字节流,转换成字符流,并且使用缓冲流读取
BufferedReader br = new BufferedReader(new InputStreamReader(is));
//读取第一行GET请求的内容
String s = br.readLine();
//按空格把它分开
String[] s1 = s.split(" ");
//把前面的"/"给排除,使用字符串的截取
String path = s1[1].substring(1);
System.out.println(path);
//创建一个fis流,读取本地的index.html文件
FileInputStream fis = new FileInputStream(path);
//获取网络输出流OutputStream,向客户端输出页面
OutputStream os = socket.getOutputStream();
// 写入HTTP协议响应头,固定写法
os.write("HTTP/1.1 200 OK\r\n".getBytes());
os.write("Content‐Type:text/html\r\n".getBytes());
// 必须要写入空行,否则浏览器不解析
os.write("\r\n".getBytes());
//向客户端输出
byte bytes[] = new byte[1024];
int len = 0;
while((len = fis.read(bytes))!=-1){
os.write(bytes);
}
//关闭资源
fis.close();
br.close();
socket.close();
}catch (IOException e){
e.printStackTrace();
}
}
}).start();
}
}
}