 |
|
 |
Anyone have any luck using this with VS2010? Works great in VS2005, but I get the below error when building in VS2010.
<pre lang="vb">GenericServer.cpp
c:\program files (x86)\microsoft visual studio 10.0\vc\include\xxresult(28): error C2825: _Fty: must be a class or namespace when followed by :: [C:\ProjectDir\ProjectName.vcxproj]
c:\program files (x86)\microsoft visual studio 10.0\vc\include\xxresult(40) : see reference to class template instantiation std::tr1::_Result_type2<__formal,_Fty,_Arg0,_Arg1 being compiled</pre>
|
|
|
|
 |
|
 |
Just add scope oprator :: before bind() like this, ::bind(...).
Gwang-Tae Kim.
0907
|
|
|
|
 |
|
 |
some real good work here :']
|
|
|
|
 |
|
 |
Thank you very nice article, i hope there's an updated version of the sample though. I learned a lot from it. Keep up the good work.
|
|
|
|
 |
|
 |
This is a very small issue I ran into: the value of the "Connection" HTTP header is written differently by IE7 and FireFox. IE uses "Keep-Alive" where FireFox uses "keep-alive". This is an issue because the code uses case-sensitive string comparison where it should be case-insensitive.
Congratulations on the excellent piece of code!
Regards,
João Paulo Figueira
DAD MVP
|
|
|
|
 |
|
 |
I see in your code that you determine request type by examining the file extension. Actually you only implement support for displaying file contents - eg html files and not program output - eg passing parameters and running a .exe file. But you DO get the file extension.
I am looking to build a http server which can use .exe programs to output status etc. Is getting the file extension in eg the GET request as you do here the way to do it? I presume the file extension can always give you the file type. eg .htm, htm or .pl, .exe, .asp, etc? Or is there another way to determine the request type?
|
|
|
|
 |
|
 |
Hello
I want to create a form which uses GET to request output from a cgi program. For example might be a form button which requests the status of a process I am running. Presently I think your program simply outputs the contents of the file - eg html file. But I want to out the returned data from a process
eg if I call output.exe param1 param2 it might return "<html><body>this is the output</body></html>"
Any guidance on how I would edit your code to cope with this.
Angus
|
|
|
|
 |
|
 |
If you use some weird caracter in the url, the browser will convert them to an hex value and will add a % in the from of that hex value. If you try to reach a file that have space for example in the filename, this server will return a 404 error.
Here is the fix for:
You will have to replace the string:
f = fopen((m_HomeDir + szFileName).c_str(), "r+b");
with
f = fopen(ConvertUrlToSystem((m_HomeDir + szFileName).c_str()), "r+b");
add that stuff somewhere:
BYTE ConvertHexToDec(char chr)
{
BYTE value = 0;
if (chr >= '0' && chr <= '9')
value = chr - '0';
else if (chr >= 'A' && chr <= 'F')
value = chr - 'A' + 0xa;
else if (chr >= 'a' && chr <= 'f')
value = chr - 'a' + 0xa;
return value;
}
char * ConvertUrlToSystem(const char * _string)
{
char * string1 = (char*)_string;
while (*string1)
{
while (*string1 && *string1 != '%') string1++;
if (*(string1+0) &&
*(string1+1) &&
*(string1+2))
{
*string1 = (ConvertHexToDec(*(string1+1)) << 4) + ConvertHexToDec(*(string1+2));
string1++;
if (*(string1+0) &&
*(string1+1) &&
*(string1+2))
{
while (*(string1+1))
{
*string1 = *(string1+2);
*string1++;
}
}
else
{
while (*string1)
{
*string1 = 0;
*string1++;
}
}
string1 = (char*)_string;
}
}
return (char*)_string;
}
|
|
|
|
 |
|
 |
First I want to say this is a very great job.
Secondly, it has problem. I am working on a http client app that is written in j2me running on motorola phone. It works well with Tomcat and MFC http server (which can be found at:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vcsample/html/_sample_mfc_httpsvr.asp)
But with this http server, I always get error response. Because the http client is very slow, server can only read the 1st block of request. This issue can be repeated if the request buffer is changed to a small size such as 16 bytes.
Can any socket expert fix this?
|
|
|
|
 |
|
 |
It should be problem with POST variables in request...this server can't work with POST/GET request I thing. But add it isn't difficult. In method "ParseRequest" parse header into eg. array and in method "IsComplete" change code to:
//if(szRequest.substr(szRequest.size() - 4, 4) == "\r\n\r\n")
if(szRequest.find("\r\n\r\n") )
.
.
.
Because POST variables are stored after \r\n\r\n. If it is there, the original method return false and server is waiting to next packet
Jarek
|
|
|
|
 |
|
 |
Thank you very much Jarek for your solution. It gives me correct direction to fix the problem. I did following change then it works fine.
In "IsComplete", as you side, check http type. If it's GET, returns TRUE only when "\r\n\r\n" is found at the end of request. If it's POST, get "content-length" from header, only when enough bytes after header is received, returns TRUE.
Thank you again.
Jeffrey
BOOL CHTTPServer::IsComplete(string szRequest)
{
BOOL Ret = FALSE;
if( szRequest.substr( 0, 3 ) == "GET" )
{
if( szRequest.substr( szRequest.size() - 4, 4 ) == "\r\n\r\n" )
{
Ret = TRUE;
}
}
else if( szRequest.substr( 0, 4 ) == "POST" )
{
int nHeaderEnd = szRequest.find( HEADER_END, 0 );
if( nHeaderEnd != -1 )
{
const char CONTENT_LENGTH[] = "\r\nContent-Length: ";
int nStart = szRequest.find( CONTENT_LENGTH, 0 );
if( nStart != -1 )
{
nStart += strlen( CONTENT_LENGTH );
int nEnd = szRequest.find( CR_LF, nStart );
string szContentLen = szRequest.substr( nStart, nEnd - nStart );
int nContentLen = atoi( szContentLen.c_str() );
if( szRequest.size() >= nHeaderEnd + 4 + nContentLen )
{
Ret = TRUE;
}
}
else
{
Ret = TRUE;
}
}
}
else
{
Ret = TRUE;
}
return Ret;
}
|
|
|
|
 |
|
 |
Hallo Jeffrey, there is maybe problem:
const char CONTENT_LENGTH[] = "\r\nContent-Length: ";
int nStart = szRequest.find( CONTENT_LENGTH, 0 );
if( nStart != -1 )
{
nStart += strlen( CONTENT_LENGTH );
int nEnd = szRequest.find( CR_LF, nStart );
string szContentLen = szRequest.substr( nStart, nEnd - nStart );
int nContentLen = atoi( szContentLen.c_str() );
if( szRequest.size() >= nHeaderEnd + 4 + nContentLen )
{
Ret = TRUE;
}
}
>>>>>>>else
>>>>>>>{
>>>>>>>Ret = TRUE;
>>>>>>>}
If content length property can't be found then isn't request complete...or my mistake? Bye, Jarek
PS: ...and missing defines for total rookies in HTTP (I am only rookie ):
#define CR_LF "\r\n"
#define HEADER_END "\r\n\r\n"
PS1: It's better to use string::npos instead -1...said to me my colleague on code review It was shame.....
|
|
|
|
 |
|
 |
How would you go about implementing authentication for a username and password for access.
Like the "Enter Network Password" dialog that shows for protected directories on web servers.
?
Thanks,
alan
|
|
|
|
 |
|
 |
I am interested in further development of this library. Also I would be interested in any bug fixes. If I find any bugs, I'll post them here. Otherwise, this class looks just like what I need. I already tested it and it performs well. Good work.
|
|
|
|
 |
|
 |
I've faced with nessesity of building an own server. The server is not HTTP but it doesn't matter. I have a question why you have prefered to build your HTTP server on clean Windows Socket API but not MFC wrapper for this function? Does any pitfalls exists in using MFC in this case?
Thanks in advance.
|
|
|
|
 |
|
 |
The MFC socket classes are bad!
You can read the Winsock FAQ about how bad it is (search Google).
Rickard Andersson
Here is my card, contact me later!
UIN: 50302279
Sonork: 37318
|
|
|
|
 |
|
 |
I see that you've used this to test out your GenericServer class. I may have a few suggestions, or things you may like to think about.
From what I've learnt about Winsock and genral IO, IO Completion ports can be really useful, in building apps that can take the strain of different types of demanding traffic by self tunning the worker threads that run off the back of the server port.
There are a couple of good articles on IOCP on CodeProject, that you may find intresting, and may even consider integrating what they have done.
Only 6 months ago when I first started experimenting with the same type of thing, that I found out, under heavy loads, the thread per connection design was not as efficient as N threads per processor.
I do like the idea of the generic base class that you have built.
Keep up the good work
Giles
|
|
|
|
 |
|
 |
I've done some testing with io completion ports and winsock event select. My experience is that there isn't any significant performance difference between the two.
My programming has been with asynchronous sockets, not the MS classes (because they require a window). See WSAEventSelect.
Another method that might be useful is "wait for completion".
|
|
|
|
 |
|
 |
How many connections did you experiment with?
With 100 or even 200 you probably won't notice too much of a difference, but once it approaches 1000 connections... good luck. IOCP is all about scalability..
|
|
|
|
 |
|
 |
You could be right here. You may have implemented some form of thread-pooling . IOCP provides a simple and easy to use threadpooling mechanism. IOCP is definitely simpler to write than using WSAEventSelect on each socket. IOCP is certainly the easiest to implement socket server thread pooling solution on Windows platforms in my opinion.
-Thomas
|
|
|
|
 |
|
 |
Hmm depends on the implementation if you in IOCP apps in workerthread implement synchronization for some kind of
logging or context deletion (dead socket cleanup) or whatever then
you loose all IDEA of IOCP . Workerthread shoudnt contain any extensive IOs (forget blocking ios)...
Simply : i saw many implementations even here on codeproject where ppl used IOCP to gain speed and scalability. but then they lost it because of wrong implementation...
i made IOCP http server without locking function and with great care about "STRANGE" IOs (others then send and recv) in workerthread and i can beat any of your wsaeventselect server for sure (iis for sure but that because another things
|
|
|
|
 |
|
 |
Hi, I would like know how the appache http server solve this problem.
AFAIK appahne is No.1 http server in the world, so we can learn a lot from there...
|
|
|
|
 |
|
 |
The unix appache http server is a very good implementation indeed. But the windows version of the appache server is only a port and isn't a very good example of an optimal windows http server implementation. I experimented a bit and I found that well done iocp is very performant for a windows box. The code must be well done and clever optimisations can be made. I found that just opening a file under windows (createfile) has significant overhead that can be bypassed by keeping a STL "map" of opened file handles + corresponding http headers. Also use "TransmitFile" as it minimises context switches from user and kernel memory spaces.
and good luck !!!
Jim
|
|
|
|
 |