使用D,我将如何侦听传入的HTTP请求并响应它们?
使用D,我将如何侦听传入的HTTP流量并对其作出响应 例如(在伪代码中): 我知道还有很多,但我还没有找到很多关于响应传入http请求的资源 编辑:使用D,我将如何侦听传入的HTTP请求并响应它们?,http,sockets,d,Http,Sockets,D,使用D,我将如何侦听传入的HTTP流量并对其作出响应 例如(在伪代码中): 我知道还有很多,但我还没有找到很多关于响应传入http请求的资源 编辑: 我当前的尝试只产生了诸如“无法创建套接字:不允许操作”之类的异常。这可能意味着我做得正确,但只是收到了一条系统错误消息。这与侦听正常传入的TCP连接并响应它们是一样的: import std.socket; Socket s = new TcpSocket(AddressFamily.INET); s.bind(new Internet
我当前的尝试只产生了诸如“无法创建套接字:不允许操作”之类的异常。这可能意味着我做得正确,但只是收到了一条系统错误消息。这与侦听正常传入的TCP连接并响应它们是一样的:
import std.socket;
Socket s = new TcpSocket(AddressFamily.INET);
s.bind(new InternetAddress("0.0.0.0", 80));
s.listen(8);
while (true) {
Socket conn=s.accept();
//handle incoming message (I'm putting it in a task pool to handle ;) )
taskPool.put(task!handleHttp(conn));
}
使用包含接收http请求和发送响应的逻辑的
handleHttp(Socket)
作为http标准(您必须找到您自己)标准库中当前没有http服务器。Adam Ruppe为Web工作提供了支持,但它目前不包括独立的Web服务器
下面的程序是一个简单的单线程基本HTTP服务器,用于教育
目的。生成有效的HTTP响应仍然取决于您;但至少是这样
解析标题,并根据标题的详细信息提供响应的机会
请求
import std.algorithm;
import std.conv;
import std.stdio;
import std.socket;
import std.string;
// usage: ./server port
void main(string[] args)
{
enum BACKLOG = 8;
ushort PORT = to!ushort(args[1]);
Socket s = new TcpSocket(AddressFamily.INET);
s.bind(new InternetAddress("0.0.0.0", PORT));
s.listen(BACKLOG);
scope (exit)
{
s.shutdown(SocketShutdown.BOTH);
s.close();
}
while (true)
{
debug writeln("waiting...");
Socket conn = s.accept();
scope (exit)
{
conn.shutdown(SocketShutdown.BOTH);
conn.close();
}
try
{
handleHttp(conn);
}
catch (Throwable e)
{
stderr.writeln("thrown: ", e);
}
}
}
void handleHttp(Socket conn)
{
// Make a buffer big enough to read a full HTTP header. My approach here is to
// read the header in its entirety before proceeding. This isn't production
// quality, but good enough for some applications.
ubyte[8192] buf; // big enough for some purposes...
size_t position, headerEnd, len, newpos;
// Receive the whole header before parsing it.
while (true)
{
len = conn.receive(buf[position..$]);
if (len == 0) // empty request
return;
newpos = position + len;
headerEnd = countUntil(buf[position..newpos], "\r\n\r\n");
position = newpos;
if (headerEnd >= 0)
break;
}
// Anything beyond headerEnd+4 is part of the request body. For now, bail:
// no POSTs or PUTs allowed. Feel free to remove the assert & implement them!
assert (position-(headerEnd+4) == 0,
"Sorry, only content-free requests are supported.");
// Now parse the header.
auto lines = splitter(buf[0..headerEnd], "\r\n");
string request_line = cast(string) lines.front;
lines.popFront;
debug writeln(request_line);
// a very simple Header structure.
struct Pair
{
string key, value;
this(ubyte[] line)
{
auto tmp = countUntil(line, ": ");
key = cast(string) line[0..tmp]; // maybe down-case these?
value = cast(string) line[tmp+2..$];
}
}
Pair[] headers;
foreach(line; lines)
headers ~= Pair(line);
auto tmp = splitter(request_line, ' ');
string method = tmp.front; tmp.popFront;
string url = tmp.front; tmp.popFront;
string protocol = tmp.front; tmp.popFront;
debug writefln("%s, %s, %s", method, url, protocol);
// Prepare a response, and send it
string resp = join(["HTTP/1.1 200 OK",
"Content-Length: 2",
"Content-Type: text/plain",
"Connection: close",
"",
"OK"],
"\r\n");
conn.send(cast(ubyte[]) resp);
}
有一个名为的多线程(基于事件)Web服务器,它支持本地D脚本
<>我从未用过D脚本,只有用它运行的C++脚本。< /P>你有没有在端口80或其他低级端口上侦听的权限?尝试使用端口8080或其他不在限制范围内的端口。我正在尝试使用端口3000。我也试过8080和其他一些。
import std.algorithm;
import std.conv;
import std.stdio;
import std.socket;
import std.string;
// usage: ./server port
void main(string[] args)
{
enum BACKLOG = 8;
ushort PORT = to!ushort(args[1]);
Socket s = new TcpSocket(AddressFamily.INET);
s.bind(new InternetAddress("0.0.0.0", PORT));
s.listen(BACKLOG);
scope (exit)
{
s.shutdown(SocketShutdown.BOTH);
s.close();
}
while (true)
{
debug writeln("waiting...");
Socket conn = s.accept();
scope (exit)
{
conn.shutdown(SocketShutdown.BOTH);
conn.close();
}
try
{
handleHttp(conn);
}
catch (Throwable e)
{
stderr.writeln("thrown: ", e);
}
}
}
void handleHttp(Socket conn)
{
// Make a buffer big enough to read a full HTTP header. My approach here is to
// read the header in its entirety before proceeding. This isn't production
// quality, but good enough for some applications.
ubyte[8192] buf; // big enough for some purposes...
size_t position, headerEnd, len, newpos;
// Receive the whole header before parsing it.
while (true)
{
len = conn.receive(buf[position..$]);
if (len == 0) // empty request
return;
newpos = position + len;
headerEnd = countUntil(buf[position..newpos], "\r\n\r\n");
position = newpos;
if (headerEnd >= 0)
break;
}
// Anything beyond headerEnd+4 is part of the request body. For now, bail:
// no POSTs or PUTs allowed. Feel free to remove the assert & implement them!
assert (position-(headerEnd+4) == 0,
"Sorry, only content-free requests are supported.");
// Now parse the header.
auto lines = splitter(buf[0..headerEnd], "\r\n");
string request_line = cast(string) lines.front;
lines.popFront;
debug writeln(request_line);
// a very simple Header structure.
struct Pair
{
string key, value;
this(ubyte[] line)
{
auto tmp = countUntil(line, ": ");
key = cast(string) line[0..tmp]; // maybe down-case these?
value = cast(string) line[tmp+2..$];
}
}
Pair[] headers;
foreach(line; lines)
headers ~= Pair(line);
auto tmp = splitter(request_line, ' ');
string method = tmp.front; tmp.popFront;
string url = tmp.front; tmp.popFront;
string protocol = tmp.front; tmp.popFront;
debug writefln("%s, %s, %s", method, url, protocol);
// Prepare a response, and send it
string resp = join(["HTTP/1.1 200 OK",
"Content-Length: 2",
"Content-Type: text/plain",
"Connection: close",
"",
"OK"],
"\r\n");
conn.send(cast(ubyte[]) resp);
}