------ android培训、java培训、期待与您交流! ----------
学到网络编程,自定义了一个服务端和客户端,出现了两个小问题,在这里记录一下。
1.用浏览器客户端访问自定义的服务器出现的问题:
自定义的服务器代码如下
package com.itheimaexercise.day24;
import java.io.*;
import java.net.*;
public class ServerTest {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
ServerSocket serverSocket = null;
try{
serverSocket = new ServerSocket(8977);
}
catch(IOException e){
e.printStackTrace();
}
Socket clientSocket = null;
try{
clientSocket = serverSocket.accept();
}
catch(IOException e){
e.printStackTrace();
}
String ip = clientSocket.getInetAddress().getHostAddress();
System.out.println(ip+"......connected");
//看看浏览器客户端访问服务器的时候都说了什么:
BufferedInputStream bufIn = null;
try{
bufIn = new BufferedInputStream(clientSocket.getInputStream());
}
catch(IOException e){
e.printStackTrace();
}
byte[] buf = new byte[1024];
int len = 0;
try{
while((len=bufIn.read(buf))!=-1){
System.out.println(new String(buf,0,len));
System.out.println();
System.out.println(new String(buf,0,len));
}
catch(IOException e){
e.printStackTrace();
}
BufferedWriter bufOut = null;
try{
bufOut = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
}
catch(IOException e){
e.printStackTrace();
}
try{
bufOut.write("<font color='red' size=6>欢迎你客户端");
bufOut.newLine();
bufOut.flush();
}
catch(IOException e){
e.printStackTrace();
}
finally{
try{
clientSocket.close();
}
catch(IOException e){
e.printStackTrace();
}
}
}
}
打开服务器后在浏览器地址栏输入 http://10.127.0.16:8977 后,服务器控制台出现如下信息:
10.127.0.16......connected
GET / HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
Accept-Language: zh-CN
User-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)
Accept-Encoding: gzip, deflate
Host: 10.127.0.16:8977
DNT: 1
Connection: Keep-Alive
而浏览器却一直处于等待状态
无法显示服务器发送的信息
说明程序卡在了某个地方,也就是所谓的阻塞了,程序无法往下执行,只能一直等待。
经过分析,代码中只有bufIn.read(buf)是阻塞式方法,程序应该是卡在这里了。
我在while中定义了 len=bufIn.read(buf)!=-1 的条件,但是客户端发来的请求消息头并没有read方法能够识别的结束标记,read方法找不到结束的那个点,只好一直等在那里,所以,不应该用len=bufIn.read(buf)!=-1作为判断的条件
经过调整,把服务器读取浏览器消息头的代码改成如下:
byte[] buf = new byte[1024];
int len = 0;
try{
//浏览器发来的消息没有结束标记,会阻塞!不能用-1判断了
len = bufIn.read(buf);
System.out.println(new String(buf,0,len));
}
catch(IOException e){
e.printStackTrace();
}
再运行,浏览器就出现了服务器发送的信息了:
————————————————————————
2.用自定义的客户端,访问Tomcat服务器中网页出现的问题:
需求:用自定义的客户端访问Tomcat myweb下的demo.html,将其内容展示在控制台上
自定义客户端代码如下:
package com.itheimaexercise.day24;
import java.net.*;
import java.io.*;
//自定义一个浏览器访问Tomcat服务器
public class ClientTest {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Socket clientSocket = null;
try{
clientSocket = new Socket("10.127.0.16",8080);
}
catch(IOException e){
e.printStackTrace();
}
BufferedWriter bufOut = null;
BufferedReader bufIn = null;
try{
bufOut = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
bufIn = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
}
catch(IOException e){
e.printStackTrace();
}
try{
bufOut.write("GET /myweb/demo.html HTTP/1.1");
bufOut.write("Accept: */*");
bufOut.write("Accept-Language: zh-cn");
bufOut.write("Host: 10.127.0.16:8977");
bufOut.write("Connection: Alive");
bufOut.newLine();
bufOut.newLine();
bufOut.flush();
}
catch(IOException e){
e.printStackTrace();
}
String line = null;
try{
while((line=bufIn.readLine())!=null){
System.out.println(line);
}
}
catch(IOException e){
e.printStackTrace();
}
finally{
try{
clientSocket.close();
}
catch(IOException e){
e.printStackTrace();
}
}
}
}
运行后出现如下信息:
HTTP/1.1 505 HTTP Version Not Supported
Server: Apache-Coyote/1.1
Date: Tue, 28 Apr 2015 07:10:23 GMT
Connection: close
很郁闷,因为跟老师写的一样,怎么出现不支持HTTP协议呢,并且原来从浏览器客户端是可以访问的啊
后来发现应该是在写请求消息头的时候出现了问题,
用write方法写的没有换行,而HTTP协议的消息头应该是一行一行的,
于是将请求消息头改成了:
try{
bufOut.write("GET /myweb/demo.html HTTP/1.1");
bufOut.newLine();
bufOut.write("Accept: */*");
bufOut.newLine();
bufOut.write("Accept-Language: zh-cn");
bufOut.newLine();
bufOut.write("Host: 10.127.0.16:8977");
bufOut.newLine();
bufOut.write("Connection: Alive");
bufOut.newLine();
bufOut.newLine();
bufOut.flush();
}
catch(IOException e){
e.printStackTrace();
}
再重新运行就OK了,搞定。
总结,在用到IO流的时候一定要注意阻塞式方法的结束标记。