创建一个服务器:
/*
创建BS版本的TCP服务器
*/
public class TCPServer {
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(8080);
Socket socket = server.accept();
InputStream is = socket.getInputStream();
while((len = is.read(bytes)) != -1){
System.out.println(new String(bytes, 0, len));
byte[] bytes = new byte[1024];
int len = 0;
}
socket.close();
server.close();
}
}
这时客户端就是浏览器,浏览器访问服务器:
服务器读取客户端的请求信息:
这时浏览器并没有收到任何响应。要想服务器给浏览器发送数据,需要向Socket对象的OutputStream对象写入以下语句:
//写入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页面(文件),我们需要读取index.html文件,就必须知道这个文件的地址,而这个地址就是请求信息的第一行。
可以使用BufferedReader中的方法readLine()读取一行。用String类的方法split(" ")获取中间部分。
服务器创建一个本地的字节输入流,根据获取到的文件路径,读取html文件,服务器端使用网络字节输出流把读取到的文件写到客户端(浏览器)显示。
实现如下:
public class TCPServer {
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(8080);
Socket socket = server.accept();
InputStream is = socket.getInputStream();
/*
while((len = is.read(bytes)) != -1){
System.out.println(new String(bytes, 0, len));
byte[] bytes = new byte[1024];
int len = 0;
}
*/
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String line = br.readLine();
//GET /demo18net/web/index.html HTTP/1.1
String[] arr = line.split(" ");
String htmlPath = arr[1].substring(1);
FileInputStream fis = new FileInputStream(htmlPath);
OutputStream os = socket.getOutputStream();
os.write("HTTP/1.1 200 OK\r\n".getBytes());
os.write("Content-Type:text/html\r\n".getBytes());
os.write("\r\n".getBytes());
int len = 0;
byte[] bytes = new byte[1024];
while((len = fis.read(bytes)) != -1){
os.write(bytes, 0, len);
}
fis.close();
socket.close();
server.close();
}
}
访问页面发现图片不能显示,原因如下:
浏览器解析服务器回写的html页面,如果页面中有图片,那么浏览器就会单独开启一个线程,读取服务器的图片,我们要让服务器一直处于监听状态,客户端请求一次,服务器就回写一次。
public class TCPServerThread {
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(8080);
while(true){
Socket socket = server.accept();
new Thread(new Runnable(){
@Override
public void run(){
try{
InputStream is = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String line = br.readLine();
String[] arr = line.split(" ");
String htmlPath = arr[1].substring(1);
System.out.println(htmlPath);
OutputStream os = socket.getOutputStream();
os.write("HTTP/1.1 200 OK\r\n".getBytes());
os.write("Content-Type:text/html\r\n".getBytes());
os.write("\r\n".getBytes());
FileInputStream fis = new FileInputStream(htmlPath);
int len = 0;
byte[] bytes = new byte[1024];
while((len = fis.read(bytes)) != -1){
os.write(bytes, 0, len);
}
fis.close();
socket.close();
}catch(IOException e){
e.printStackTrace();
}
}
}).start();
}
}
}
控制台输出如下:
GET /src/demo18net/web/index.html HTTP/1.1
GET /src/demo18net/web/img/logo2.png HTTP/1.1
GET /src/demo18net/web/img/header.jpg HTTP/1.1
GET /src/demo18net/web/img/1.jpg HTTP/1.1
GET /src/demo18net/web/img/big01.jpg HTTP/1.1
GET /src/demo18net/web/img/middle01.jpg HTTP/1.1
GET /src/demo18net/web/img/title2.jpg HTTP/1.1
GET /src/demo18net/web/img/ad.jpg HTTP/1.1
GET /src/demo18net/web/img/small03.jpg HTTP/1.1
GET /src/demo18net/web/img/footer.jpg HTTP/1.1
GET /favicon.ico HTTP/1.1
java.io.FileNotFoundException: favicon.ico (系统找不到指定的文件。)
at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(FileInputStream.java:195)
at java.io.FileInputStream.<init>(FileInputStream.java:138)
at java.io.FileInputStream.<init>(FileInputStream.java:93)
at demo18net.web.TCPServerThread$1.run(TCPServerThread.java:30)
at java.lang.Thread.run(Thread.java:748)
浏览器显示如下: