两种方法实现一个简单的web服务器.docx
- 文档编号:724826
- 上传时间:2023-04-29
- 格式:DOCX
- 页数:22
- 大小:76.55KB
两种方法实现一个简单的web服务器.docx
《两种方法实现一个简单的web服务器.docx》由会员分享,可在线阅读,更多相关《两种方法实现一个简单的web服务器.docx(22页珍藏版)》请在冰点文库上搜索。
两种方法实现一个简单的web服务器
计算机网络报告
实现一个简单的web服务器
实现一个简单的web服务器
用Java实现一个简单的web服务器
方法1:
packagecom.wow.server;
importjava.io.File;
importjava.io.IOException;
importjava.io.InputStream;
importjava.io.OutputStream;
import.InetAddress;
import.ServerSocket;
import.Socket;
import.UnknownHostException;
/**
*一个简单的web应用服务器
*/
publicclassHttpServer{
publicstaticfinalStringWEB_ROOT=System.getProperty("user.dir")+File.separator+"webroot";
privatestaticfinalStringSHUTDOWN_COMMAND="/SHUTDOWN";
privatebooleanshutdown=false;
publicstaticvoidmain(String[]args){
HttpServerserver=newHttpServer();
server.start();
}
//启动服务器,并接收用户请求进行处理
publicvoidstart(){
ServerSocketserverSocket=null;
intPORT=8080;
try{
serverSocket=newServerSocket(PORT,1,InetAddress.getByName("127.0.0.1"));
}catch(UnknownHostExceptione){
e.printStackTrace();
System.exit(-1);
}catch(IOExceptione){
e.printStackTrace();
System.exit(-1);
}
//若请求的命令不为SHUTDOWN时,循环处理请求
while(!
shutdown){
Socketsocket=null;
InputStreaminput=null;
OutputStreamoutput=null;
try{
//创建socket进行请求处理
socket=serverSocket.accept();
input=socket.getInputStream();
output=socket.getOutputStream();
//接收请求
Requestrequest=newRequest(input);
request.parser();
//处理请求并返回结果
Responseresponse=newResponse(output);
response.setRequest(request);
response.sendStaticResource();
//关闭socket
socket.close();
//若请求命令为关闭,则关闭服务器
shutdown=request.getUri().equals(SHUTDOWN_COMMAND);
}catch(IOExceptione){
e.printStackTrace();
continue;
}
}
}
}
该类本身是一个应用程序,包含main方法,直接通过java命令即可运行。
在运行时,它本身会启动一个ServerSocket类用于监听服务器的某个端口。
当接收到的命令不是停止服务器的SHUTDOWN时,它会创建一个Socket套接字,用于接收请求及返回响应结果。
Request类则用于请求的接收,对于Http协议来讲,通过浏览器向服务器发送请求有一定的格式,其实Request也就是接收这些请求信息,并对其进行分析,抽取出所需的信息,包括cookie、url等。
其中http发送的请求包括三部分:
请求方法统一资源标识符协议/版本
请求头
请求实体
其中请求头与请求实体间有一个空行,具体的示例代码如下所示:
GET/index.htmHTTP/1.1
Host:
Connection:
keep-alive
User-Agent:
Mozilla/5.0(WindowsNT6.1)AppleWebKit/537.11(KHTML,likeGecko)Chrome/23.0.1271.97Safari/537.11
Accept:
text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding:
gzip,deflate,sdch
Accept-Language:
zh-CN,zh;q=0.8Accept-Charset:
GBK,utf-8;q=0.7,*;q=0.3
Cookie:
BAIDUID=D275C16E04D9BB2CF55FD9B9654AECAC:
FG=1;
BDREFER=%7Burl%3A%22http%3A//BDUT=5b2fD275C16E04D9BB2CF55FD9B9654AECAC138a495329b1;MCITY=-%3A;shifen[3113720932]=1357565900;H_PS_PSSID=1445_1661
Request类用于接收socket套接字发送过来的字节流,并按照http协议请求的格式进行解析。
对于简单的web服务器而言,我们只需要解析出它的uri即可,这样即可以通过通过文件匹配的方式找到对应的资源。
具体的实现代码如下所示:
packagecom.wow.server;
importjava.io.IOException;
importjava.io.InputStream;
/**
*接收到的请求串的具体格式如下:
*GET/aaa.htmHTTP/1.1
*Host:
127.0.0.1:
8080
*Connection:
keep-alive
*User-Agent:
Mozilla/5.0(WindowsNT6.1)AppleWebKit/537.11(KHTML,likeGecko)Chrome/23.0.1271.97Safari/537.11
*Accept:
text/html,application/xhtml+xml,application/xml;q=0.9,q=0.8
*Accept-Encoding:
gzip,deflate,sdch
*Accept-Language:
zh-CN,zh;q=0.8
*Accept-Charset:
GBK,utf-8;q=0.7,*;q=0.3
*
*/
publicclassRequest{
privateInputStreaminput;
privateStringuri;
publicRequest(InputStreaminput){
this.input=input;
}
publicvoidparser(){
StringBufferrequest=newStringBuffer();
byte[]buffer=newbyte[2048];
inti=0;
try{
i=input.read(buffer);
}catch(IOExceptione){
e.printStackTrace();
i=-1;
}
for(intk=0;k
request.append((char)buffer[k]);
}
uri=parserUri(request.toString());
}
privateStringparserUri(StringrequestData){
intindex1,index2;
index1=requestData.indexOf('');
if(index1!
=-1){
index2=requestData.indexOf('',index1+1);
if(index2>index1){
returnrequestData.substring(index1+1,index2);
}
}
returnnull;
}
publicStringgetUri(){
returnuri;
}
}
通过上述代码可以看出parser方法用于解析具体请求,它接收socket的字节流,对其进行处理,获取其中的uri信息。
当获取到uri信息后,即可将uri对应到服务器的某个应用或目录中。
本文只是实现了一个简单的静态资源服务器,即将uri对应到某个目录下的文件,若文件存在则打开并读取文件信息;若不存在则直接返回一段错误信息。
Response类即用于处理该逻辑,同时它会将文件流写回至socket套接字中,由socket套接字将响应结果返回给客户端。
对于http协议而言,响应也是有一定的格式要求的,不能发送任意格式的信息,否则浏览器是无法接收并处理的。
Http响应结果也包括三部分:
协议状态码描述
响应头
响应实体段
其中响应头与响应实体段间也是有一个空行的,具体的实例如下所示:
HTTP/1.1200OK
Date:
Mon,07Jan201314:
31:
36GMT
Server:
BWS/1.0
Content-Length:
4029
Content-Type:
text/html;charset=gbk
Cache-Control:
privateExpires:
Mon,07Jan201314:
31:
36GMT
Content-Encoding:
gzip
Set-Cookie:
H_PS_PSSID=1445_1661;path=/;domain=
Connection:
Keep-Alive
…Response类中当访问请求的文件不存在时,需要发送一段固定的响应文本给客户端,该段响应文档的格式必须严格按照http响应格式进行组织,否则客户端接收不到。
具体的实现源码如下所示:
packagecom.wow.server;
importjava.io.File;
importjava.io.FileInputStream;
importjava.io.IOException;
importjava.io.OutputStream;
/**
*响应结果
*/
publicclassResponse{
privateOutputStreamoutput;
privateRequestrequest;
privatestaticfinalintBUFFER_SIZE=1024;
publicResponse(OutputStreamoutput){
this.output=output;
}
publicvoidsetRequest(Requestrequest){
this.request=request;
}
//发送一个静态资源给客户端,若本地服务器有对应的文件则返回,否则返回404页面
publicvoidsendStaticResource(){
byte[]buffer=newbyte[BUFFER_SIZE];
intch;
FileInputStreamfis=null;
try{
Filefile=newFile(HttpServer.WEB_ROOT,request.getUri());
if(file.exists()){
fis=newFileInputStream(file);
ch=fis.read(buffer);
while(ch!
=-1){
output.write(buffer,0,ch);
ch=fis.read(buffer,0,BUFFER_SIZE);
}
}else{
StringerrorMessage="HTTP/1.1404FileNotFound\r\n"+
"Content-Type:
text/html\r\n"+
"Content-Length:
24\r\n"+
"\r\n"+
"
FileNotFound!
";
output.write(errorMessage.getBytes());
}
}catch(Exceptione){
System.out.println(e.toString());
}finally{
if(fis!
=null){
try{
fis.close();
}catch(IOExceptione){
e.printStackTrace();
}
}
}
}
}
方法2:
importjava.io.IOException;
importjava.io.OutputStream;
importjava.io.PrintWriter;
import.Socket;
publicclassHTTPThreadimplementsRunnable{
privateSocketsocket;
privateintcount;
publicHTTPThread(){
}
publicHTTPThread(Socketsocket,intcount){
this.socket=socket;
this.count=count;
}
@Override
publicvoidrun(){
//TODOAuto-generatedmethodstub
try{
OutputStreamos=socket.getOutputStream();
PrintWriterpw=newPrintWriter(os);
pw.println("");
pw.println("
");pw.println("
");pw.println("Thismypage!
Youarewelcome!
");
pw.println("");
pw.println("");
pw.println("");
pw.flush();
pw.close();
os.close();
}catch(IOExceptione){
e.printStackTrace();
}
}
}
importjava.io.IOException;
import.ServerSocket;
import.Socket;
publicclassTCPServer{
publicstaticvoidmain(String[]args){
intcount=1;
try{
ServerSocketss=newServerSocket(8080);
Sockets=null;
while((s=ss.accept())!
=null){
System.out.println("Thevisitor:
"+count);
HTTPThreadhttpThread=newHTTPThread(s,count);
Threadthread=newThread(httpThread);
thread.start();
count++;
}
}catch(IOExceptione){
e.printStackTrace();
}
}
}
编译运行后,通过浏览器访问http:
//localhost:
8080/就可以了,是不是很神奇呢!
用C语言实现一个简单的web编程
#include
#include
#include
#include
#include
#include
#include
#include
#include
#defineEOL"\r\n"
#defineEOL_SIZE2
typedefstruct{
char*ext;
char*mediatype;
}extn;
//Possiblemediatypes
extnextensions[]={
{"gif","image/gif"},
{"txt","text/plain"},
{"jpg","image/jpg"},
{"jpeg","image/jpeg"},
{"png","image/png"},
{"ico","image/ico"},
{"zip","image/zip"},
{"gz","image/gz"},
{"tar","image/tar"},
{"htm","text/html"},
{"html","text/html"},
{"php","text/html"},
{"pdf","application/pdf"},
{"zip","application/octet-stream"},
{"rar","application/octet-stream"},
{0,0}};
/*
Ahelperfunction
*/
voiderror(constchar*msg){
perror(msg);
exit
(1);
}
/*
Ahelperfunction
*/
intget_file_size(intfd){
structstatstat_struct;
if(fstat(fd,&stat_struct)==-1)
return
(1);
return(int)stat_struct.st_size;
}
/*
Ahelperfunction
*/
voidsend_new(intfd,char*msg){
intlen=strlen(msg);
if(send(fd,msg,len,0)==-1){
printf("Errorinsend\n");
}
}
/*
Thisfunctionrecievesthebuffer
untilan"Endofline(EOL)"byteisrecieved
*/
intrecv_new(intfd,char*buffer){
char*p=buffer;//Useofapointertothebufferratherthandealingwiththebufferdirectly
inteol_matched=0;//Usetocheckwhethertherecievedbyteismatchedwiththebufferbyteornot
while(recv(fd,p,1,0)!
=0)//Startreceiving1byteatatime
{
if(*p==EOL[eol_matched])//ifthebytematcheswiththefirsteolbytethatis'\r'
{
++eol_matched;
if(eol_matched==EOL_SIZE)//ifboththebytesmatcheswiththeEOL
{
*(p+1-EOL_SIZE)='\0';//Endthestring
return(strlen(buffer));//Returnthebytesrecieved
}
}else{
eol_matched=0;
}
p++;//Incrementthepointertoreceivenextbyte
}
return(0);
}
/*
Ahelperfunction:
Returnsthe
webrootlocation.
*/
char*
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 方法 实现 一个 简单 web 服务器