GVKun编程网logo

java实现一个简单的Web服务器实例解析File Not FoundHello World!(java编写web服务器)

14

在这篇文章中,我们将带领您了解java实现一个简单的Web服务器实例解析FileNotFoundHelloWorld!的全貌,包括java编写web服务器的相关情况。同时,我们还将为您介绍有关Ajax

在这篇文章中,我们将带领您了解java实现一个简单的Web服务器实例解析File Not FoundHello World!的全貌,包括java编写web服务器的相关情况。同时,我们还将为您介绍有关Ajax完成一个简单的HelloWorld程序、Apache Web服务器,Java Web服务 – Hello World教程、C 语言实现一个简单的 web 服务器、c# – 构建一个简单的Web服务器,我可以作为Windows服务运行的知识,以帮助您更好地理解这个主题。

本文目录一览:

java实现一个简单的Web服务器实例解析File Not FoundHello World!(java编写web服务器)

java实现一个简单的Web服务器实例解析File Not FoundHello World!(java编写web服务器)

这篇文章主要介绍了java实现一个简单的Web服务器实例解析,分享了相关代码示例,小编觉得还是挺不错的,具有一定借鉴价值,需要的朋友可以参考下

Web服务器也称为超文本传输协议服务器,使用http与其客户端进行通信,基于java的web服务器会使用两个重要的类,

java.net.socket类和java.net.ServerSocket类,并基于发送http消息进行通信。

这个简单的Web服务器会有以下三个类:

*HttpServer

*Request

*Response

应用程序的入口在HttpServer类中,main()方法创建一个HttpServer实例,然后调用其await()方法,顾名思义,await()方法会在指定端口上等待HTTP请求,对其进行处理,然后发送响应信息回客户端,在接收到关闭命令前,它会保持等待状态。

该应用程序仅发送位于指定目录的静态资源的请求,如html文件和图像,它也可以将传入到的http请求字节流显示到控制台,但是,它并不发送任何头信息到浏览器,如日期或者cookies等。

下面为这几个类的源码

Request:package cn.com.server; import java.io.InputStream; public class Request { private InputStream input; private String uri; public Request(InputStream input){ this.input=input; } public void parse(){ //Read a set of characters from the socket StringBuffer request=new StringBuffer(2048); int i; byte[] buffer=new byte[2048]; try { i=input.read(buffer); } catch (Exception e) { e.printstacktrace(); i=-1; } for (int j=0;jindex1){ return requestString.substring(index1+1,index2); } } return null; } public String getUri(){ return this.uri; } }Request类表示一个HTTP请求,可以传递InputStream对象来创建Request对象,可以调用InputStream对象中的read()方法来读取HTTP请求的原始数据。上述源码中的parse()方法用于解析Http请求的原始数据,parse()方法会调用私有方法parseUrI()来解析HTTP请求的URI,除此之外,并没有做太多的工作,parseUri()方法将URI存储在变量uri中,调用公共方法getUri()会返回请求的uri。Response:package cn.com.server; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.OutputStream; /** * HTTP Response = Status-Line * *(( general-header | response-header | entity-header ) CRLF) * CRLF * [message-body] * Status-Line=Http-Version SP Status-Code SP Reason-Phrase CRLF * */ public class Response { private static final int BUFFER_SIZE=1024; Request request; OutputStream output; public Response(OutputStream output){ this.output=output; } public void setRequest(Request request){ this.request=request; } public void sendStaticResource()throws IOException{ byte[] bytes=new byte[BUFFER_SIZE]; FileInputStream fis=null; try { File file=new File(HttpServer.WEB_ROOT,request.getUri()); if(file.exists()){ fis=new FileInputStream(file); int ch=fis.read(bytes,0,BUFFER_SIZE); while(ch!=-1){ output.write(bytes, 0, BUFFER_SIZE); ch=fis.read(bytes, 0, BUFFER_SIZE); } } else{ //file not found String errorMessage="HTTP/1.1 404 File Not Foundrn"+ "Content-Type:text/htmlrn"+ "Content-Length:23rn"+ "rn"+ "

File Not Found

"; output.write(errorMessage.getBytes()); } } catch (Exception e) { System.out.println(e.toString()); } finally{ if(fis!=null){ fis.close(); } } } }Response对象在HttpServer类的await()方法中通过传入套接字中获取的OutputStream来创建。Response类有两个公共方法:setRequest()和sendStaticResource() ,setRequest()方法会接收一个Request对象为参数,sendStaticResource()方法用于发送一个静态资源到浏览器,如Html文件。HttpServer:package cn.com.server; import java.io.File; import java.io.InputStream; import java.io.OutputStream; import java.net.InetAddress; import java.net.ServerSocket; import java.net.socket; public class HttpServer { /** * WEB_ROOT is the directory where our html and other files reside. * For this package,WEB_ROOT is the "webroot" directory under the * working directory. * the working directory is the location in the file system * from where the java command was invoke. */ public static final String WEB_ROOT=System.getProperty("user.dir")+File.separator+"webroot"; private static final String SHUTDOWN_COMMAND="/SHUTDOWN"; private Boolean shutdown=false; public static void main(String[] args) { HttpServer server=new HttpServer(); server.await(); } public void await(){ ServerSocket serverSocket=null; int port=8080; try { serverSocket=new ServerSocket(port,1,InetAddress.getByName("127.0.0.1")); } catch (Exception e) { e.printstacktrace(); System.exit(0); } while(!shutdown){ Socket socket=null; InputStream input=null; OutputStream output=null; try { socket=serverSocket.accept(); input=socket.getInputStream(); output=socket.getoutputStream(); //create Request object and parse Request request=new Request(input); request.parse(); //create Response object Response response=new Response(output); response.setRequest(request); response.sendStaticResource(); } catch (Exception e) { e.printstacktrace(); continue; } } } }这个类表示一个Web服务器,这个Web服务器可以处理对指定目录的静态资源的请求,该目录包括由公有静态变量final WEB_ROOT指明的目录及其所有子目录。现在在webroot中创建一个html页面,命名为index.html,源码如下:Insert title here

Hello World!

现在启动该WEB服务器,并请求index.html静态页面。

所对应的控制台的输出:

如此,一个简单的http服务器便完成了。

总结

以上就是本文关于java实现一个简单的Web服务器实例解析的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!

Ajax完成一个简单的HelloWorld程序

Ajax完成一个简单的HelloWorld程序

总结

以上是小编为你收集整理的Ajax完成一个简单的HelloWorld程序全部内容。

如果觉得小编网站内容还不错,欢迎将小编网站推荐给好友。

Apache Web服务器,Java Web服务 – Hello World教程

Apache Web服务器,Java Web服务 – Hello World教程

有谁知道我在哪里可以找到设置apache和java web服务(Hello World)的好教程?

我是Apache和Java Web Services的新手(我需要Tomcat吗?).我需要一个简单的Java Web服务,它可以从客户端接收一个简单的http请求(例如www.somedomain.com/service/001/notify).我们的想法是客户端将发出Http请求,Java Web Service将接收请求并在主机上运行相应的Java代码.

对不起我的知识空白,因此我需要有一个教程.

总之,我想这样做:

客户:

new Request("www.somedomain.com/service/001/notify");

JAVA WEB服务:

public void notify(int serviceID){
    System.out.println("Service " + serviceID + " says 'Hello!'");
}
最佳答案
This video is slightly outdated; but it is a good tutorial for an absolute beginner.

此外,Tomcat是所谓的servlet容器.要查看servlet容器和Web服务之间的区别,这是一个有用的线程:Difference between servlet and web service

你应该记住,Tomcat只是众多选择中的一个.如果您需要将它用于学校/工作,那就去吧.但如果您有自由选择,那么我建议使用谷歌应用程序引擎java(这里的教程:http://code.google.com/appengine/docs/java/gettingstarted/).在引擎盖下他们使用德比(我认为谷歌的大部分产品都在德比上运行,但我肯定不知道).

我推荐的原因是因为我迄今为止设置servlet / etc app引擎的经验是最简单的.它还有一个免费的主机配额,你应该可以留下来,因为这显然是一个微不足道的/学习经验.就哪些servlet容器比其他容器更好而言,我认为它不会影响你的曝光程度.虽然我已经和他们搞乱了好几年了但现在对我来说并不重要……

C 语言实现一个简单的 web 服务器

C 语言实现一个简单的 web 服务器

说到 web 服务器想必大多数人首先想到的协议是 http,那么 http 之下则是 tcp,本篇文章将通过 tcp 来实现一个简单的 web 服务器。

本篇文章将着重讲解如何实现,对于 http 与 tcp 的概念本篇将不过多讲解。

一、了解 Socket 及 web 服务工作原理

既然是基于 tcp 实现 web 服务器,很多学习 C 语言的小伙伴可能会很快的想到套接字 socket。socket 是一个较为抽象的通信进程,或者说是主机与主机进行信息交互的一种抽象。socket 可以将数据流送入网络中,也可以接收数据流。

socket 的信息交互与本地文件信息的读取从表面特征上看类似,但其中所存在的编写复杂度是本地 IO 不能比拟的,但却有相似点。在 win 下 socket 的交互交互步骤为:WSAStartup 进行初始化--> socket 创建套接字--> bind 绑定--> listen 监听--> connect 连接--> accept 接收请求--> send/recv 发送或接收数据--> closesocket 关闭 socket--> WSACleanup 最终关闭。

了解完了一个 socket 的基本步骤后我们了解一下一个基本 web 请求的用户常规操作,操作分为:打开浏览器-->输入资源地址 ip 地址-->得到资源。当目标服务器接收到该操作产生掉请求后,我们可以把服务器的响应流程步骤看为:获得 request 请求-->得到请求关键数据-->获取关键数据-->发送关键数据。服务器的这一步流程是在启动socket 进行监听后才能响应。通过监听得知接收到请求,使用 recv 接收请求数据,从而根据该参数得到进行资源获取,最后通过 send 将数据进行返回。

二、创建sokect完成监听

2.1 WSAStartup初始化

首先在c语言头文件中引入依赖 WinSock2.h:

include <WinSock2.h>

在第一点中对 socket 的创建步骤已有说明,首先需要完成 socket 的初始化操作,使用函数 WSAStartup,该函数的原型为:

int WSAStartup(
WORD wVersionRequired,
LPWSADATA lpWSAData
);

该函数的参数 wVersionRequired 表示 WinSock2 的版本号;lpWSAData 参数为指向 WSADATA 的指针,WSADATA 结构用于 WSAStartup 初始化后返回的信息。

wVersionRequired 可以使用 MAKEWORD 生成,在这里可以使用版本 1.1 或版本2.2,1.1 只支持 TCP/IP,版本 2.1 则会有更多的支持,在此我们选择版本 1.1。

首先声明一个 WSADATA 结构体  :

WSADATA wsaData;

随后传参至初始化函数 WSAStartup 完成初始化:

WSAStartup(MAKEWORD(1, 1), &wsaData)

WSAStartup 若初始化失败则会返回非0值:

if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0)
{
exit(1);
}

2.2 创建socket 套接字

初始化完毕后开始创建套接字,套接字创建使用函数,函数原型为:

SOCKET WSAAPI socket(
int af,
int type,
int protocol
);

在函数原型中,af 表示 IP 地址类型,使用 PF_INET 表示 IPV4,type 表示使用哪种通信类型,例如 SOCK_STREAM 表示 TCP,protocol 表示传输协议,使用 0 会根据前 2 个参数使用默认值。

int skt = socket(PF_INET, SOCK_STREAM, 0);

创建完 socket 后,若为 -1 表示创建失败,进行判断如下:

if (skt == -1)
{
return -1;
}

2.3 绑定服务器

创建完 socket 后需要对服务器进行绑定,配置端口信息、IP 地址等。 首先查看 bind 函数需要哪一些参数,函数原型如下:

int bind(
SOCKET socket,
const sockaddr *addr,
int addrlen
);

参数 socket 表示绑定的 socket,传入 socket 即可;addr 为 sockaddr_in 的结构体变量的指针,在 sockaddr_in 结构体变量中配置一些服务器信息;addrlen 为 addr 的大小值。

通过 bind 函数原型得知了我们所需要的数据,接下来创建一个 sockaddr_in 结构体变量用于配置服务器信息:

struct sockaddr_in server_addr;

随后配置地址家族为AF_INET对应TCP/IP:

server_addr.sin_family = AF_INET;

接着配置端口信息:

server_addr.sin_port = htons(8080);

再指定 ip 地址:

server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");

ip 地址若不确定可以手动输入,最后使用神器 memset 初始化内存,完整代码如下:

//配置服务器
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(8080);
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
memset(&(server_addr.sin_zero), ''0'', 8);

随后使用 bind 函数进行绑定且进行判断是否绑定成功:

//绑定
if (bind(skt, (struct sockaddr *)&server_addr,sizeof(server_addr)) == -1) {
return -1;
}

2.4 listen进行监听

绑定成功后开始对端口进行监听。查看 listen 函数原型:

int listen(
int sockfd,
int backlog
)

函数原型中,参数 sockfd 表示监听的套接字,backlog 为设置内核中的某一些处理(此处不进行深入讲解),直接设置成 10 即可,最大上限为 128。使用监听并且判断是否成功代码为:

if (listen(skt, 10) == -1 ) {
return -1;
}

此阶段完整代码如下:

include <WinSock2.h>

include<stdio.h>

int main(){
//初始化
WSADATA wsaData;
if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0) {
exit(1);
}
//socket创建
int skt = socket(PF_INET, SOCK_STREAM, 0);
if (skt == -1) {
return -1;
}
//配置服务器
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(8080);
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
memset(&(server_addr.sin_zero), ''0'', 8);
//绑定
if (bind(skt, (struct sockaddr *)&server_addr,sizeof(server_addr)) == -1){
return -1;
}
//监听
if (listen(skt, 10) == -1 ) {
return -1;
}

printf("Listening ... ...n");
}

运行代码可得知代码无错误,并且输出 listening:

在这里插入图片描述

2.5 获取请求

监听完成后开始获取请求。受限需要使用 accept 对套接字进行连接,accept 函数原型如下:

int accept(
int sockfd,
struct sockaddr *addr,
socklen_t *addrlen
);

参数 sockfd 为指定的套接字;addr 为指向 struct sockaddr 的指针,一般为客户端地址;addrlen 一般设置为设置为 sizeof(struct   sockaddr_in) 即可。代码为:

struct sockaddr_in c_skt;
int s_size=sizeof(struct sockaddr_in);
int access_skt = accept(skt, (struct sockaddr *)&c_skt, &s_size);

接下来开始接受客户端的请求,使用recv函数,函数原型为:

ssize_t recv(
int sockfd,
void *buf,
size_t len,
int flags
)

参数 sockfd 为 accept 建立的通信;buf 为缓存,数据存放的位置;len 为缓存大小;flags 一般设置为0即可:

//获取数据
char buf[1024];
if (recv(access_skt, buf, 1024, 0) == -1) {
exit(1);
}

此时我们再到 accpt 和 recv 外层添加一个循环,使之流程可重复:

while(1){
//建立连接
printf("Listening ... ...n");
struct sockaddr_in c_skt;
int s_size=sizeof(struct sockaddr_in);
int access_skt = accept(skt, (struct sockaddr *)&c_skt, &s_size);

//获取数据
char buf[1024];
if (recv(access_skt, buf, 1024, 0) == -1) {
exit(1);
}
}

并且可以在浏览器输入 127.0.0.1:8080 将会看到客户端打印了 listening 新建了链接:

我们添加printf语句可查看客户端请求:

while(1){
//建立连接
printf("Listening ... ...n");
struct sockaddr_in c_skt;
int s_size=sizeof(struct sockaddr_in);
int access_skt = accept(skt, (struct sockaddr *)&c_skt, &s_size);

//获取数据
char buf[1024];
if (recv(access_skt, buf, 1024, 0) == -1) {
exit(1);
}

printf("%s",buf);
}

接下来我们对请求头进行对应的操作。

2.6 请求处理层编写

得到请求后开始编写处理层。继续接着代码往下写没有层级,编写一个函数名为 req,该函数接收请求信息与一个建立好的连接为参数:

void req(char* buf, int access_socket)
{
}

然后先在 while 循环中传递需要的值:

req(buf, access_skt);

接着开始编写 req 函数,首先在 req 函数中标记当前目录下:

char arguments[BUFSIZ];
strcpy(arguments, "./");

随后分离出请求与参数:

char command[BUFSIZ];
sscanf(request, "%s%s", command, arguments+2);

接着我们标记一些头元素:

char* extension = "text/html";
char* content_type = "text/plain";
char* body_length = "Content-Length: ";

接着获取请求参数,若获取 index.html,就获取当前路径下的该文件:

FILE* rfile= fopen(arguments, "rb");

获取文件后表示请求 ok,我们先返回一个 200 状态:

char* head = "HTTP/1.1 200 OKrn";
int len;
char ctype[30] = "Content-type:text/htmlrn";
len = strlen(head);

接着编写一个发送函数 send_:

int send_(int s, char buf, int len)
{
int total;
int bytesleft;
int n;
total=0;
bytesleft=*len;
while(total < *len)
{
n = send(s, buf+total, bytesleft, 0);
if (n == -1)
{
break;
}
total += n;
bytesleft -= n;
}
*len = total;
return n==-1?-1:0;
}

send 函数功能并不难在此不再赘述,就是一个遍历发送的逻辑。随后发送 http 响应与文件类型:

send_(send_to, head, &len);
len = strlen(ctype);
send_(send_to, ctype, &len);

随后获得请求文件的描述,需要添加头文件#include <sys/stat.h>使用fstat,且向已连接的通信发生必要的信息 :

//获取文件描述
struct stat statbuf;
char read_buf[1024];
char length_buf[20];
fstat(fileno(rfile), &statbuf);
itoa( statbuf.st_size, length_buf, 10 );
send(client_sock, body_length, strlen(body_length), 0);
send(client_sock, length_buf, strlen(length_buf), 0);

send(client_sock, "n", 1, 0);
send(client_sock, "rn", 2, 0);

最后发送数据:

//·数据发送
char read_buf[1024];
len = fread(read_buf ,1 , statbuf.st_size, rfile);
if (send_(client_sock, read_buf, &len) == -1) {
printf("error!");
}

最后访问地址 http://127.0.0.1:8080/index.html,得到当前目录下 index.html 文件数据,并且在浏览器渲染:

所有代码如下:

include <WinSock2.h>

include<stdio.h>

include <sys/stat.h>

//来源:公众号(c语言与cpp编程)

int send_(int s, char buf, int len) {
int total;
int bytesleft;
int n;
total=0;
bytesleft=*len;
while(total < *len)
{
n = send(s, buf+total, bytesleft, 0);
if (n == -1)
{
break;
}
total += n;
bytesleft -= n;
}
*len = total;
return n==-1?-1:0;
}

void req(char* request, int client_sock) {
char arguments[BUFSIZ];
strcpy(arguments, "./");

char command[BUFSIZ];
sscanf(request, "%s%s", command, arguments+2);

char* extension = "text/html";
char* content_type = "text/plain";
char* body_length = "Content-Length: ";

FILE* rfile= fopen(arguments, "rb");

char* head = "HTTP/1.1 200 OKrn";
int len;
char ctype[30] = "Content-type:text/htmlrn";
len = strlen(head);

send_(client_sock, head, &len);
len = strlen(ctype);
send_(client_sock, ctype, &len);

struct stat statbuf;

char length_buf[20];
fstat(fileno(rfile), &statbuf);
itoa( statbuf.st_size, length_buf, 10 );
send(client_sock, body_length, strlen(body_length), 0);
send(client_sock, length_buf, strlen(length_buf), 0);

send(client_sock, "n", 1, 0);
send(client_sock, "rn", 2, 0);

char read_buf[1024];
len = fread(read_buf ,1 , statbuf.st_size, rfile);
if (send_(client_sock, read_buf, &len) == -1) {
printf("error!");
}

return;
}

int main(){
WSADATA wsaData;
if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0) {
exit(1);
}

int skt = socket(PF_INET, SOCK_STREAM, 0);
if (skt == -1) {
return -1;
}

struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(8080);
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
memset(&(server_addr.sin_zero), ''0'', 8);

if (bind(skt, (struct sockaddr *)&server_addr,sizeof(server_addr)) == -1) {
return -1;
}

if (listen(skt, 10) == -1 ) {
return -1;
}

while(1){

printf("Listening ... ...n");
struct sockaddr_in c_skt;
int s_size=sizeof(struct sockaddr_in);
int access_skt = accept(skt, (struct sockaddr *)&c_skt, &s_size);

char buf[1024];
if (recv(access_skt, buf, 1024, 0) == -1) {
exit(1);
}

req(buf, access_skt);
}

}

小伙伴们可以编写更加灵活的指定资源类型、错误处理等完善这个 demo。

c# – 构建一个简单的Web服务器,我可以作为Windows服务运行

c# – 构建一个简单的Web服务器,我可以作为Windows服务运行

我是一名Web开发人员,所以我的经验都是使用 ruby,python或 PHP.但是,我要做一些小窗口编程.

我想构建一个轻量级的Web服务器,它可以处理传入的请求并将它们传递给COM端口.我希望能够将它作为一个exe分发,将服务器安装为Windows服务.

您认为最好的语言是什么?什么IDE最适合所说的语言?

谢谢,
赛斯

解决方法

说实话,你可能会在C#中做得最开心.学习曲线会更小,语言和大多数功能都是你的朋友.您可以在2分钟内设置Windows服务,这也是一个优势.

我们今天的关于java实现一个简单的Web服务器实例解析File Not FoundHello World!java编写web服务器的分享已经告一段落,感谢您的关注,如果您想了解更多关于Ajax完成一个简单的HelloWorld程序、Apache Web服务器,Java Web服务 – Hello World教程、C 语言实现一个简单的 web 服务器、c# – 构建一个简单的Web服务器,我可以作为Windows服务运行的相关信息,请在本站查询。

本文标签: