This problem is driving me crazy! I've read all the questions on Stack Overflow but I'm still stuck.
My as3 program works very well, but when I have finished it and put it on a server, it starts to request this famous policy file.
AS3 script:
socket.addEventListener(Event.CONNECT, onConnect);
socket.addEventListener(Event.CLOSE, onClose);
socket.addEventListener(IOErrorEvent.IO_ERROR, onError);
socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecError);
socket.addEventListener(ProgressEvent.SOCKET_DATA, onResponse);
socket.connect( MYHOST, 4242 );
C# server code:
TcpListener serverSocket = new TcpListener(4242);
TcpClient clientSocket = default(TcpClient);
serverSocket.Start();
clientSocket = serverSocket.AcceptTcpClient();
NetworkStream networkStream = clientSocket.GetStream();
StreamReader read = new StreamReader(networkStream, Encoding.UTF8);
StreamWriter write = new StreamWriter(networkStream, Encoding.UTF8);
response = read.ReadLine();
if (response.Contains("policy"))
{
write.Write("<?xml version=\"1.0\"?><cross-domain-policy><allow-access-from domain=\"*\" to-ports=\"*\" /></cross-domain-policy>\0");
write.Flush();
clientSocket.Close();
return;
}
So, when the AS3 doesn't find the policy on the default port 843 (or something similar), it asks directly on the same socket as the connection.
My C# code sees the request and replies, after which the AS3 script closes the connection (which is OK), but it never reconnects.
I have tried to put this in the AS3 before the connect():
Security.loadPolicyFile( "xmlsocket://myhost.com:4242");
But when I do the connect() it simply gets stuck and never requests the policy file. After I close the AS3 application, my server sees the request, but the connection is closed. It's like the client forget to do a flush.
Can someone tell me how I can solve this problem correctly?
After 3 days i have finally discovered what is the bug in the code.
A bounty of 50 points and no one have noticed it :-(
Is very stupid, a novice error:
When the flash application ask for the policy file dont send the newline char, but the terminating char '\0'.
and im reading with the read.ReadLine(); that read until the '\n', so it stuck.
Thank you all for your replies.
I've faced a problem similar to your's. The fact is, that while running a Flash app into a C#, it lose lot's of requests which port differs from standart. The solution is not to use such requests in Flash. So you have to put them into C#, and call this functions with Flash's ExternalInterface.call. When the request is completed, your C# must call a Flash function, passing req's answer as a parameter.
Related
I've recently started learning about computer networks and decieded to try TCP/IP server and client. They both work, but I'm having issues with sending mutliple data to the server. I've made it to look like a chat service between clients but the server accepts only one client and closes the connection after the data is sent and the client for some reason stops responding after sending data to server (I think the problem comes from the server and not the client itself), no error message, only on the server side when I force close the client.
This is how my server looks like...
static void Main(string[] args)
{
//User can define port
Console.WriteLine("open a port:");
string userInputPort = Console.ReadLine();
//listening for connections
TcpListener listener = new TcpListener(System.Net.IPAddress.Any, Convert.ToInt32(userInputPort));
listener.Start();
Console.WriteLine("listening...");
while (true)
{
//waiting for client to connect to server
Console.WriteLine("Waiting for connection...");
//when user connects to server, server will accept any request
TcpClient client = listener.AcceptTcpClient();
Console.WriteLine("Client Accepted");
NetworkStream stream = client.GetStream();
StreamReader streamR = new StreamReader(client.GetStream());
StreamWriter streamW = new StreamWriter(client.GetStream());
while (true)
{
if(client.Connected)
{
if (stream.CanRead)
{
//buffer
byte[] buffer = new byte[1024];
stream.Read(buffer, 0, buffer.Length);
int recv = 0;
foreach (byte b in buffer)
{
if(b != 0)
{
recv++;
}
}
string request = Encoding.UTF8.GetString(buffer, 0, recv);
Console.WriteLine("request recived: " + request);
streamW.Flush();
}
}
}
}
}
}
}
and this is how the client looks like...
...
try
{
//try to connect
client = new TcpClient(textBoxIP.Text, Convert.ToInt32(textBoxPort.Text));
}
...
static void sendMessage(string message, TcpClient client)
{
int byteCount = Encoding.ASCII.GetByteCount(message);
byte[] sendData = new byte[byteCount];
sendData = Encoding.ASCII.GetBytes(message);
NetworkStream stream = client.GetStream();
stream.Write(sendData, 0, sendData.Length);
StreamReader streamReader = new StreamReader(stream);
string respone = streamReader.ReadLine();
stream.Close();
client.Close();
}
Like I said, I'm still learning about computer networking and any comment to this code will help!
Thank you
It helps if you give yourself some idea of what you're actually expecting from the code you're writing. It seems to me that you make a lot of automatic assumptions without actually making sure to put them in your code.
Your server can only ever at best accept a single client. Not one client at a time, but one ever. You never exit from your reading loop, so after the client disconnects, you end up in a wonderful infinite busy loop. Your intent was probably to serve another client when one disconnects, but that's not what you're doing.
You assume the server will send a response to the client. But you never actually send any response! For a client to read something, the server first must send something for the client to read.
You assume the string sent by the client will be zero-terminated, or that the target buffer for Read will be zeroed. If you want zero-termination, you have to send it yourself from the client - the StreamWriter certainly doesn't do that. Strings aren't zero-terminated as a rule - it's just one C-style way of representing strings in memory. You shouldn't assume anything about the contents of the buffer beyond what the return value from Read tells you was returned.
Those are issues with things you forgot to quite put in, presumably. Now to the incorrect assumptions on part of how TCP works. To keep clarity, I will tell the way it is, rather than the incorrect assumption.
A single write can result in multiple reads on the other side, and a single read can read data from multiple writes on the other side. TCP doesn't send (and receive) messages, it deals with streams. You need to add a messaging protocol on top of that if streams aren't good enough for you.
Read returns how many bytes were read. Use that to process the response, instead of looking for a zero. When Read returns a zero, it means the connection has been closed, and you should close your side as well. This is all that you need, instead of all the while (true), if (Connected) and if (CanRead) - loop until Read returns zero. Process data you get as it gets to you.
The TCP stream is a bit trickier to work with than most streams; it behaves differently enough that using helpers like StreamReader is dangerous. You have to do the work yourself, or get a higher-abstraction library to work with networking. TCP is very low level.
You cannot rely on getting a response to a Read. TCP uses connections, but it doesn't do anything to keep the connection alive on its own, or notice when it is down - it was designed for a very different internet than today's, and it can happily survive interruptions of service for hours - as long as you don't try to send anything. If the client disconnects abruptly, the server might never know.
You should also make sure to clean up all the native resources properly - it really helps to use using whenever possible. .NET will clean up eventually, but for things like I/O, that's often dangerously late.
while (true)
{
if(client.Connected)
{
if (stream.CanRead)
{
I don't see any code, that exits the outer while the loop if either client.Connected or stream.CanRead become false. So, when the client disconnects and they become false, it seems to me that the server just loops forever.
You should at least do all error handling (close all necessary streams) and break out of the loop.
As the next problem, you code can only have one client at a time. If the client is not actually closing the connection. I do not know for sure what the correct C# solution is, but i think it is spawning a separate thread for each connected client.
i have few questions about programming a TcpListener.
First problem:
Once client is connected using browser, i see the request. it is all ok. but then i face the problem with writing. and client recieving that data. it basically never gets a reply from server. do i need that flush function ? how does it work ? and is there any others ways of doing it ?
Porblem number 2 which is even more weird. when i call client.close() client doesnt go anywhere. it is still there. browser is stillw ating for data. and when i kill connection in the browser, only then Tcp client gets closed and loop starts again.
namespace TestServer
{
class Program
{
public static void Main()
{
TcpListener server;
IPAddress addr = IPAddress.Parse("127.0.0.1");
server = new TcpListener(addr, 80);
server.Start();
byte[] buffer = new byte[1024];
while(true)
{
string data = null;
Console.WriteLine("Awaiting for connections");
TcpClient client = server.AcceptTcpClient();
Console.WriteLine("Connected...");
NetworkStream str = client.GetStream();
int msgCounter;
while ((msgCounter = str.Read(buffer, 0, buffer.Length)) != 0)
{
Console.WriteLine("Processing stream...");
data += System.Text.Encoding.ASCII.GetString(buffer, 0, msgCounter);
Console.WriteLine("Reciaved: {0}", System.Text.Encoding.ASCII.GetString(buffer, 0, msgCounter));
}
byte[] response = System.Text.Encoding.ASCII.GetBytes("200 OK");
str.Write(response, 0, response.Length);
str.Flush();
client.Close();
buffer = new byte[1024];
}
}
}
}
TCP as a bi-directional transport layer protocol does not denote any concept of the "client is done sending request" signal.
What it means for developers is that such signaling must be defined in the application (or any other higher level) protocol layer.
In your case it is declared by HTTP itself in the https://tools.ietf.org/html//rfc2616#section-5
So if you intend to implement an HTTP server you must parse the HTTP request that has a determined way to identify the end of the request (see the link above).
To summarise: you need to know somehow you've read the request entirely and you may start processing it and generating/sending the response.
I'd recommend you to start with a million times proven working MSDN example of TcpListener class. Additionally I can point to explicit wrong approach:
Do not recreate buffer, it is a waste of resources.
Do not use browser as a test client if you are working with TCP sockets. Any browser tries to correct somehow HTTP protocol errors and can do it in very unpredictable way. If you need HTTP level of debugging, use Fiddler, for lower levels - Microsoft Network Monitor, Wireshark of Netcat.
It could be useful to read some book about TCP/IP networking. Particularly, you will know, that there is not "close" operation or command for TCP connection by protocol definition, TcpClient just emulate it. Instead a peer can send "shutdown" to another one, it does mean it doesn't plan to send data anymore, but can read it. Connection can be considered as closed only after both peers have sent their "shutdown" and received "shutdown" from each other.
I have written a TCP chat in C# WPF for one client and server (it works). Now I would like to extend this program to have many clients in chat.
client code: http://pastebin.com/Zv1Me6P4
server code: http://pastebin.com/VYBJCA9f
I was checking everything and I guess that streamreader readline fails.
In my program, client sends message to server, which sends to everybody and appears message in their TextBoxs.
How my program works:
Start server
Connect Client1, Client2
Client1 sends message "a" ... nothing happens
Client1 sends message "b" ... nothing happens
Client2 sends message "c" ... both clients got "ac"
Streamreader blocks and I dont know how to unblock it. Okay, I can use new thread; +1 client = +1 thread, but it sounds so strange. I was really reading stackOverFlow and I found sth like: while((line = reader.ReadLine()) != null) or !reader.EndOfStream or reader.pike > 0.. all that doesn't work... or I do it incorrenctly.
Reading my code you can be confused:
in client program there is some server ( it's old overwritten project )
I create for every clients new Reader and Writer Stream; I got to know that I can use one R/W Stream but I couldn't use it however.. Because I use List list so: reader(list.getByte()) does't work.
I beg you please help me. It's small unsolved piece of my work, which makes me upset. I love programming when problems are resonable and possible to solve.
Thanks for all comment under my post.
I had a similar problem not being able to ReadLine and ReadToEnd would exceed my timeouts. This worked for me
string line = "";
while (reader.Peek() > -1) {
line += (char)reader.Read();
}
I've written a number of small programs that communicate via TCP. I'm having endless issues with the system hanging because one program has closed its network connection, and the other end-point somehow fails to notice that it's now disconnected.
I was expecting doing I/O on a TCP connection that has been closed to throw some kind of I/O exception, but instead the program seems to just hang, waiting forever for the other end-point to reply. Obviously if the connection is closed, that reply is never coming. (It doesn't even seem to time out if you leave it for, say, twenty minutes.)
Is there some way I can force the remote end to "see" that I've closed the network connection?
Update: Here is some code...
public sealed class Client
{
public void Connect(IPAddress target)
{
var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Connect(ipAddress, 1177);
_stream = new NetworkStream(socket);
}
public void Disconnect()
{
_stream.Close();
}
}
public sealed class Server
{
public void Listen()
{
var listener = new TcpListener(IPAddress.Any, 1177);
listener.Start();
var socket = listener.AcceptSocket();
_stream = new NetworkStream(socket);
...
}
public void Disconnect()
{
socket.Shutdown(SocketShutdown.Both);
socket.Disconnect(false);
}
}
When an application closes a socket the right way, it sends a message containing 0 bytes. In some cases you may get a SocketException indicating something went wrong. In a third situation, the remote party is no longer connected (for instance by unplugging the network cable) without any communication between the two parties.
If that last thing happens, you'll have to write data to the socket in order to detect that you can no longer reach the remote party. This is why keep-alive mechanisms were invented - they check every so often whether they can still communicate with the other side.
Seeing the code you posted now: when using NetworkStream the Read operation on it would return a value of 0 (bytes) to indicate that the client has closed the connection.
The documentation is mentions both
"If no data is available for reading, the Read method returns 0."
and
"If the remote host shuts down the connection, and all available data has been received, the Read method completes immediately and return zero bytes."
in the same paragraph. In reality NetworkStream blocks if no data is available for reading while the connection is open.
Hi MathematicalOrchid,
You might find what you are looking for here:
http://blog.stephencleary.com/2009/05/detection-of-half-open-dropped.html
There is some great information there when it comes to working with TCP sockets and detecting half open connections.
You can also refer to this post which seems to have the same solution:
TcpClient communication with server to keep alive connection in c#?
-Dave
You are opening the socket, and assigning it to the stream. At the end of the process, you close the network stream, but not the socket.
For NetworkStream.Close() to close the underlying socket it must have the ownership parameters set to true in the constructor - See MSDN Docs at http://msdn.microsoft.com/en-us/library/te7e60bx.aspx.
This may result in the connection hanging as the underlying socket was not correctly closed.
Change
_stream = new NetworkStream(socket);
To
_stream = new NetworkStream(socket, true);
On a side note, if you do not require a maximum performance for your small app you should try using TCPClient instead - http://msdn.microsoft.com/en-us/library/system.net.sockets.tcpclient%28v=vs.100%29.aspx. This is a wrapper around socket and it provides connection state checking facilities.
Thanks for reading and answering in advance!
I wrote a simple C# program that connects via sockets with a third-party tool. Whenever I send a string longer than 1024 characters, the third-party software throws an error. Now I am trying to find out if this is a problem of my socket code or one of the other software (EnergyPlus).
It is only a few lines of code, and if anyone has suggestions, they would be highly appreciated!
using System.IO;
using System.Net;
using System.Net.Sockets;
...
private int port = 1410;
private TcpListener listener;
private Stream s;
private StreamReader sr;
private StreamWriter sw;
private Socket soc;
...
Here it really starts:
listener = new TcpListener(port);
listener.Start();
soc = listener.AcceptSocket();
// now, the other program connects
soc.SetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.ReceiveTimeout, 10000);
s = new NetworkStream(soc);
sr = new StreamReader(s);
sw = new StreamWriter(s);
sw.AutoFlush = true; // enable automatic flushing
sw.WriteLine("more or less than 1024 characters");
...
This is the code I use. Anything I forgot? Anything I should take care of?
I am glad about any suggestions.
The error I get from E+ is the following:
ExternalInterface: Socket communication received error value " 1" at time = 0.00 hours.
ExternalInterface: Flag from server " 0".
Yu need to look at the specification defined by EnergyPlus; any socket communication needs rules. There are two obvious options here:
you aren't following the rules (maybe it is limited length, or maybe you need to write special marker bytes for this scenario)
their server code doesn't implement the specification correctly (biggest causes are: buffer issues, or: assuming a logical frame arrives in a single network packet)
Actually, I find it interesting that it is doing anything yet, as there is no obvious "frame" there; TCP is a stream, so you ususally need frames to divide logical messages. This usually means one of:
a length prefix, with or without other header data
a cr/lf/crlf terminator (or other terminator), usually for text-based protocols
closing the socket (the ultimate terminator)
You do none of those, so in any server I write, that would be an incomplete message until something else happens. It sounds text-based; I'd try adding a cr/lf/crlf