A few things to be aware of using your suggested architecture:
Trying to send an HTTP request over sockets
Principally, you need to be aware that even though you can chat http at a lower level using sockets, there are a large number of cases where communication in this fashion will fail. Mainly these failures will occur if the user has a proxy server enabled in their browser, as there is no effective means of discovering and subsequently using the proxy when connecting via a socket.
In order to make a policy server, you can use the TcpListener class. You would start listening as follows:
var tcpListener = new TcpListener(IPAddress.Any, 843 );
tcpListener.start();
tcpListener.BeginAcceptTcpClient(new AsyncCallback(NewClientHandler), null);
The method NewClientHandler would have the form:
private void NewClientHandler(IAsyncResult ar)
{
TcpClient tcpClient = tcpListener.EndAcceptTcpClient(ar);
...
At which point you might want to supply the tcpClient object to a class of your own creation to handle the validation of the data coming from the socket. I'm going to call it RemoteClient.
In RemoteClient, you'd have something like this:
var buffer=new byte[BUFFER_SIZE];
tcpClient.GetStream().BeginRead(buffer, 0, buffer.Length, Receive, null);
and a Receive method:
private void Receive(IAsyncResult ar)
{
int bytesRead;
try
{
bytesRead = tcpClient.GetStream().EndRead(ar);
}
catch (Exception e)
{
//something bad happened. Cleanup required
return;
}
if (bytesRead != 0)
{
char[] charBuffer = utf8Encoding.GetChars(buffer, 0, bytesRead);
try
{
tcpClient.GetStream().BeginRead(buffer, 0, buffer.Length, Receive, null);
}
catch (Exception e)
{
//something bad happened. Cleanup required
}
}
else
{
//socket closed, I think?
return;
}
}
and some send methods:
public void Send(XmlDocument doc)
{
Send(doc.OuterXml);
}
private void Send(String str)
{
Byte[] sendBuf = utf8Encoding.GetBytes(str);
Send(sendBuf);
}
private void Send(Byte[] sendBuf)
{
try
{
tcpClient.GetStream().Write(sendBuf, 0, sendBuf.Length);
tcpClient.GetStream().WriteByte(0);
tcpClient.GetStream().WriteByte(13); //very important to terminate XmlSocket data in this way, otherwise Flash can't read it.
}
catch (Exception e)
{
//something bad happened. cleanup?
return;
}
}
That's all the important details I think. I wrote this some time ago... the Receive method looks like it could do with a rework, but it should be enough to get you started.
I've been testing this locally and everything seems to be working fine until the socket gets closed. Shouldn't the socket not get closed? After the message is sent to the Flex client, the Java code does:
_in.close();
_out.close();
_socket.close();
Then the Flex client gets the sandbox violation the next time it tries to communicate with the socket. If I create a new socket connection again then send and receive works fine, followed by a close. But after a minute or so I get another sandbox violation. I wonder if Flash is trying to ping the socket and since it's closed it throws the sandbox violation?
Best Answer
ISPs can do whatever the heck they want to irrespective to the IANA. There are tons of ports registered with IANA, but vast majority of them are blocked on the inbound unless that ISP runs those services. That's the point of firewalls to block connections to ports you don't run services for.
So you have to assume people will be accessing your application over the web browser on networks that sit behind firewalls. The admins of those firewalls could block all outbound traffic except over a few ports like 22 (SSH), 25 (SMTP), 80 (HTTP) 110 (POP3), 143 (IMAP), 443 (HTTPS), etc. Typically, traffic sent outbound is not limited to only those ports because restricting it causes a lot of headaches for the firewall admin because it can interfere with people doing their job. It's just easier to let the traffic out. And there is little risk of it having an impact on network security. More likely those ports and many others ports ARE blocked for inbound traffic.
Typically most users who are on a corporate network or a managed network have access to computers that sit behind the firewall and can make outbound connections, but nothing outside the firewall can connect to them. That's typically called network segmentation where the computers used by its employees sit in a more restricted area, and the corps servers live in the DMZ which do have inbound access to limited number of ports. Your server you're connecting to most likely lives in the DMZ and that's why you had to ask for port 843 to be opened. And your admin is just saying if someone running the game has outbound traffic limited they won't be able to use your game because their firewall might block 843 outbound access.
The bottom line? Those people sitting behind firewalls that can't access port 843 will be unable to run your game. Typically these are corporate or government environments that have tight control over what you can and can't do with company machines. How many of these exist? It's in the minority, but basically it just means they shouldn't be playing games on company time so it's probably not a big deal that they can't access it. You could just code for the possibility and tell them "You do not have access to X, and this game requires it, yada yada yada." If you really wanted to know how prevalent it is you could record it by sending a request back to your server to measure it. Or you could find a way to put your SWF on the same domain as your server which would negate the need for 843.