I am trying to create a very simple HTTP server, I need to be able to
load my browser and enter a URL like
http://127.0.0.1:12345/index.html
and have my server provide that page. It's only used on the local
machine (will never be needed on the Internet itself).
I'm running on Windows XP. I launch a thread, and the thread (code
below) sits there, waiting for connection requests. Problem is,
accept() never returns. I try loading http://127.0.0.1:12345/index.html
in both FF and IE, nothing. I try telnet 127.0.0.1 12345, nothing. I
try telnet 192.168.1.50 12345, nothing (that's my machine's IP on my
LAN).
If I create a socket inside my server application (in its main thread,
not in the server thread) and connect to socket 12345, that works, so
it appears my code is basically correct, but my socket can't be seen
outside of the application itself?
Thanks in advance for helping me with this (undoubtedly stupid) error.
Chris
UINT CServerThread::ThreadProc(void)
{
WSADATA wsaData;
sockaddr_in address;
TRACE("CServerThread::ThreadProc() in thread %d [this=%p]\n",
GetCurrentThreadId(), this);
int iErr = WSAStartup(MAKEWORD(2, 2), &wsaData);
// WSAStartup() returned 0 in 0 msec
if (iErr)
{
TRACE(" WSAStartup() failed with error %d\n", iErr);
return false;
}
m_bStarted = true;
m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
// socket() returned 11596 in 0 msec
if (m_socket == INVALID_SOCKET)
{
TRACE(" socket() failed with error %d\n", WSAGetLastError());
return false;
}
memset(&address, 0, sizeof(address));
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY; // inet_addr("127.0.0.1");
address.sin_port = 12345; // 0; // bind() should pick an unused
port
iErr = bind(m_socket, (SOCKADDR*)&address, sizeof(address));
// bind() returned 0 in 0 msec
if (iErr == SOCKET_ERROR)
{
TRACE(" bind() failed with error %d\n", WSAGetLastError());
return false;
}
int nBytes = sizeof(address);
memset(&address, 0, sizeof(address));
iErr = getsockname(m_socket, (SOCKADDR*)&address, &nBytes);
// getsockname() returned 0, 16/16 in 0 msec
if (iErr == SOCKET_ERROR)
{
TRACE(" getsockname() failed with error %d, %d/%d\n",
WSAGetLastError(), nBytes, sizeof(address));
return false;
}
TRACE(" Socket is using port %d\n", address.sin_port);
iErr = listen(m_socket, SOMAXCONN);
// listen() returned 0 in 31 msec
if (iErr == SOCKET_ERROR)
{
TRACE(" listen() failed with error %d\n", WSAGetLastError());
return false;
}
m_iPort = address.sin_port;
for (;;)
{
sockaddr_in from;
int fromlen = sizeof(from);
DWORD lTick = GetTickCount();
SOCKET socket = accept(m_socket, (sockaddr*)&from, &fromlen);
TRACE(" accept() returned %d in %d msec\n", socket, GetTickCount()
- lTick);
Sleep(500);
}
return 0;
}
By the way, yes this code is a little odd right now, if accept() were
to succeed, nothing would actually happen, plus I'm returning 'false'
from a function that claims to be returning a UINT. I figured that
once accept() started returning, I would write the rest of the code,
and I keep moving the function around between being in my main thread
and being in the CServerThread, which is why the return code is off.
Please don't get hung up on those mistakes, they shouldn't materially
affect the network-ability of this code.
Is the socket really listening? netstat -an should confirm that.
How do you spawn the thread. Usng beginthreadex?
UNT,
Jag
On Feb 20, 12:28 am, Chris Shearer Cooper
> affect the network-ability of this code.- Hide quoted text -
>
> - Show quoted text -
The program this lives inside is MFC/C++, so I use the MFC function
AfxBeginThread() which does eventually call _beginthreadex().
Regarding netstat, that's a great idea, unfortunately the results make
me even more confused.
I'm opening on a hard-coded port # of 26386 (that's a port that was
reported unused during some of my testing), and that port # doesn't
appear in the netstat listing at all.
However, if I connect to that port from inside the same program (I'll
paste the code below), it succeeds. The connect() is happy, and
accept() returns me a socket, so life is good. And _still_ the
connection doesn't appear in netstat.
Am I somehow not in TCP/IP? Or how am I doing this, such that this
connection works, but doesn't show up? I'm so confused.
Thanks,
Chris
sockaddr_in address;
SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
memset(&address, 0, sizeof(address));
address.sin_family = AF_INET;
address.sin_addr.s_addr = inet_addr("127.0.0.1");
address.sin_port = m_thread.GetPort();
int iErr = connect(sock, (sockaddr*)&address, sizeof(address));
// connect() returns zero (success)!
The port the above binds to is actually 14640. The port number (and
other elements except "sin_family") in the SOCKADDR_IN structure is in
network order, not host order.
You are likely making the same mistake in both your server and client
code within your program, so they still wind up using the same port and
the client can connect to the server. But any other code (e.g. a telnet
program) that you think should be using 12345 as the port won't connect,
because you're actually using a different port.
Try this:
memset(&address, 0, sizeof(address));
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(12345);
Pete
Woot! You are the man. I know it had to be something simple and
obvious. Go have a beer (or drink of your choice) and send me the
bill.
Chris