I want connect with my jabber server and read server answer:
DnsEndPoint host = new DnsEndPoint("talk.google.com", 5222);
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
SocketAsyncEventArgs args = new SocketAsyncEventArgs();
public void start()
{
string message = "<?xml version=1.0?><stream:streamto='gmail.com'xmlns='jabber:client'xmlns:stream='http://etherx.jabber.org/streams'version='1.0'>";
var buffer = Encoding.UTF8.GetBytes(message);
args.RemoteEndPoint = host;
args.Completed += SocketAsyncEventArgs_Completed;
args.SetBuffer(buffer, 0, buffer.Length);
bool completesAsynchronously = socket.ConnectAsync(args);
if (!completesAsynchronously)
{
SocketAsyncEventArgs_Completed(args.ConnectSocket, args);
}
}
private void SocketAsyncEventArgs_Completed(object sender, SocketAsyncEventArgs e)
{
if (e.SocketError != SocketError.Success)
{
Deployment.Current.Dispatcher.BeginInvoke(() => MessageBox.Show("Error during socket operation: " + e.SocketError));
return;
}
byte[] buffer = e.Buffer;
XDocument temp = ConvertByteArrayToXml(buffer);
}
XDocument ConvertByteArrayToXml(byte[] data)
{
XmlReaderSettings settings = new XmlReaderSettings();
using (MemoryStream stream = new MemoryStream(data))
using (XmlReader reader = XmlReader.Create(stream, settings))
{
return XDocument.Load(reader);
}
}
At Return XDocument.Load(reader) I get exeption '1.0' is an unexpected token. The expected token is '"' or '''. How can solve it?
Why I want it? Because when I authorize myself and change status it not affect it at my account.
Please do not write your own XMPP library from scratch, but choose one of the existing ones.
You're not going to be successful thinking of the XML you receive like a file, which is where your Unexpected end of file has occurred error is coming from. You must parse the XML incrementally.
This (in your declaration for message):
<?xml version=1.0?>
is an invalid XML declaration. As per the exception, you want:
<?xml version="1.0" ?>
Note that this has nothing to do with Jabber or sockets, and everything to do with XML. It's important to pay attention to exception messages and stack traces, so you can diagnose this sort of thing for yourself: you need to be able to isolate the area of the problem, so you can tackle just that one bit in isolation.
(The rest of that XML looks pretty bust, too, by the way.)
Related
I have a simple client and server in C#. The goal is for the client to send an XML document to the server, and then the server should respond with a different XML document. The server is blocking when I try to receive the input/request XML with XmlDocument.Load(NetworkStream).
Server:
TcpListener t = new TcpListener(IPAddress.Any, 4444);
t.Start();
TcpClient c = t.AcceptTcpClient();
NetworkStream s = c.GetStream();
XmlDocument req = new XmlDocument();
req.Load(s);
string respString = "<response><data>17</data></response>";
XmlDocument resp = new XmlDocument();
resp.LoadXml(respString);
resp.Save(s);
Client:
TcpClient t = new TcpClient("localhost", 4444);
NetworkStream s = t.GetStream();
string reqStr = "<request><parameters><param>7</param><param>15</param></parameters></request>";
XmlDocument req = new XmlDocument();
req.LoadXml(reqStr);
req.Save(s);
XmlDocument resp = new XmlDocument();
resp.Load(s);
Console.WriteLine(resp.OuterXml);
I tried adding a Flush() in the client after it saves the request XmlDocument to the stream, but that didn't seem to help. Originally I tried having the server read all of the input from the client to a MemoryStream, but then I found that there was no way to signify to the server that all the input was done without disconnecting, which meant that then the client couldn't read its input.
I can send XML input to the server from a file with netcat and everything works fine. This works whether I use XmlDocument.Load(NetworkStream) in the server, or read all the input into a MemoryStream. What is it that netcat is doing in this case that I am not doing in my C# client, and how do I do it in C#? Should I be going about this differently?
Tcp connection is bidirectional, and you can close one half of it while still having the other half open. In this case, you can close client to server half after sending all data, and then you can receive response over server to client half still. You can do it for your example like this:
TcpClient t = new TcpClient("localhost", 4444);
NetworkStream s = t.GetStream();
string reqStr = "<request><parameters><param>7</param><param>15</param></parameters></request>";
XmlDocument req = new XmlDocument();
req.LoadXml(reqStr);
req.Save(s);
// important line here! shutdown "send" half of the socket connection.
t.Client.Shutdown(SocketShutdown.Send);
XmlDocument resp = new XmlDocument();
resp.Load(s);
Console.WriteLine(resp.OuterXml);
Don't forget dispose network stream on a server's side after you sent all data:
TcpListener t = new TcpListener(IPAddress.Loopback, 4444);
t.Start();
TcpClient c = t.AcceptTcpClient();
using (NetworkStream s = c.GetStream()) {
XmlDocument req = new XmlDocument();
req.Load(s);
Console.WriteLine("Got request: {0}", req.OuterXml);
string respString = "<response><data>17</data></response>";
XmlDocument resp = new XmlDocument();
resp.LoadXml(respString);
resp.Save(s);
}
Actually if whole communication is single request followed by single response - you can use this technique instead of custom protocols over tcp (remember to use timeouts and properly dispose your streams and tcp clients).
Otherwise, remember that network stream is kind of open connection between client and server - it does not have explicit "end". When you are doing XmlDocument.Load - it will read until it is possible (that is until Read returns with 0 bytes read), so it blocks in your case. You should define your own protocol over tcp, so that you yourself can define the message boundary. Simple way would be - first 4 bytes define the length of the following message. So you read first 4 bytes and then read until that length is reached or timeout occurs.
So, I finally managed to make a conection but now im trying to pass images over the server.
The code looks like this:
private void Form1_Load(object sender, EventArgs e)
{
//StartConnectionVideo();
Client = new TcpClient();
Client.Connect("10.0.0.3", 456);
//Connect to 127.0.0.1 on port 3700
readingThread = new Thread(new ThreadStart(StartReading));
//Start a new thread to receive images
readingThread.Start();
}
private void StartReading()
{
while (true)
{
MessageBox.Show("D");
NetworkStream stream = Client.GetStream();
BinaryFormatter formatter = new BinaryFormatter();
Image img = Image.FromStream(stream);
MessageBox.Show("D");
//Deserialize the image from the NetworkStream
MessageBox.Show(img.Width.ToString());
pictureBox1.Image = img; //Show the image in the picturebox
}
}
}
the first message box work(directlry after the loop) but on the second its stuck.
it's just hangs on this line
Image img = Image.FromStream(stream);
the server side is this..
Image img=Image.FromFile(#"C:\Users\איתמר\Desktop\air\amumu_0.jpg");
VideoServer a = new VideoServer(img ,this);
a.StartListening();
//a.padre.pictureBox1.Image = img;
a.SendImage(img);
videoserver is a class i wrote... i'll write here the main important code pieces
public void StartListening()
{
// Create the TCP listener object using the IP of the server and the specified port
tlsClient = new TcpListener (IPAddress.Any, 456);
// Start the TCP listener and listen for connections
tlsClient.Start();
// The while loop will check for true in this before checking for connections
ServRunning = true;
thrListener = new Thread(KeepListening);
thrListener.Start();
}
public void SendImage(Image img)
{
for (int i = 0; i < ClientList.Count; i++)
{
TcpClient tempClient = (TcpClient)ClientList[i];
if (tempClient.Connected) //If the client is connected
{
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(tempClient.GetStream(), img);
//Serialize the image to the tempClient NetworkStream
}
else
{
ClientList.Remove(tempClient);
i--;
}
}
i think i've showed the main code... the rest isnt so important because im prettry sure the problem is in this code...
i appriciate any help of you guys im breaking my head over a week :D
You are serializing the image using BinaryFormatter but deserializing it using Image.FromStream. These are two incompatible formats. You must use the same format both times.
As far as I'm aware Image.FromStream is not documented to cope with infinite streams. In fact I'm quite sure it doesn't because by principle it cannot avoid reading two much (except if it were reading byte-wise which is a performance nightmare). Therefore, you can't use Image.FromStream directly.
I'd do this by first converting the image to a byte[] or a MemoryStream. Then I would first write the length of the image data and then the data. A length prefix is a common way of serializing things.
Or, use a higher-level abstraction such as protobuf.
I have a requirement to get the data into a string using TcpClient. The site requires authentication as well. I found a snippet to get data into stream but it is throwing
exception that the connection terminated unexpectedly
. Below is the sample code
TcpClient oClient = new TcpClient();
oClient.Connect("xxx.xxx.xxx.xxx", 80);
NetworkStream ns = oClient.GetStream();
StreamWriter sw = new StreamWriter(ns);
sw.Write(
string.Format(
"GET /{0} HTTP/1.1\r\nUser-Agent: {1}\r\nHost: iq\r\n\r\n",
"/",
"MyTCPClient")
);
sw.Flush();
StringBuilder sb = new StringBuilder();
while (true)
{
int i = ns.ReadByte(); // Inefficient but more reliable
if (i == -1) break; // Other side has closed socket
sb.Append((char)i); // Accrue 'c' to save page data
}
oClient.Close();
How can I include the authentication step as well.
P.S.: Just to summarize, I want to get the html of a page in string using TcpClient which involves authentication as well.
Edit: I am going for this approach as the URL had period at the end which was being removed by URI.
I'm relatively new to C# but here goes:
I am developing a remote file service client/server console application in C# which is supposed to exchange messages using synchronous sockets.
One of the main problems (even thought it might seem simple) is to return a string from the server, to the client using streamreader/streamwriter.
The application user a command line interface with options (from a switch statement) to execute actions. I.e. typing 1 and enter would execute the code to send the string from the server to the client.
Below is a sample code from the client:
try
{
using (TcpClient client = (TcpClient)clientObject)
using (NetworkStream stream = client.GetStream())
using (StreamReader rd = new StreamReader(stream))
using (StreamWriter wr = new StreamWriter(stream))
{
string menuOption = rd.ReadLine();
switch (menuOption)
{
case "1":
case "one":
string passToClient = "Test Message!";
wr.WriteLine(passToClient);
break;
}
while (menuOption != "4");
}
}
I understand the code I posted is just a snippet of the program, but it would take up a fair amount of space and was hoping you can gather what I mean from this, if not I will post more.
This is just to give a general idea of what I am going for,
I appreciate any help / advice you can give. Its not so much code examples I'm looking for (although a little would help) but more some explanation on streamreader/writer as I cant seem to understand much of what is online.
Thanks.
I think you're just missing a wr.flush(); but this article should cover everything you need:
http://thuruinhttp.wordpress.com/2012/01/07/simple-clientserver-in-c/
Whenever you use StreamWriter you need to Flush() the contents of the stream. I'll quote MSDN as the reason becomes quite clear:
Clears all buffers for the current writer and causes any buffered data to be written to the underlying stream.
You can call it quite simply like:
wr.flush();
Solution can be simpler:
StreamWriter wr = new StreamWriter(stream) { AutoFlush = true }
I just ran a test using your code, and it works fine, I can step right into the "one" case statement.
I am guessing you are either not including the line-break in the string you are sending, or you just have the TcpClient or TcpListener configured wrong.
Here is the Client-Side code for my test:
TcpClient client = new TcpClient("127.0.0.1", 13579);
string message = "one" + Environment.NewLine;
Byte[] data = System.Text.Encoding.ASCII.GetBytes(message);
NetworkStream stream = client.GetStream();
stream.Write(data, 0, data.Length);
Here is the Server-Side:
IPAddress localAddr = IPAddress.Parse("127.0.0.1");
TcpListener server = new TcpListener(localAddr, 13579);
server.Start();
TcpClient client = server.AcceptTcpClient();
using (client)
using (NetworkStream stream = client.GetStream())
using (StreamReader rd = new StreamReader(stream))
using (StreamWriter wr = new StreamWriter(stream))
{
string menuOption = rd.ReadLine();
switch (menuOption)
{
case "1":
case "one":
string passToClient = "Test Message!";
wr.WriteLine(passToClient);
break;
}
while (menuOption != "4") ;
}
Just run the server-side code first, which will block while waiting for connection and then while waiting for data. Then run the client-side code. You should be able to catch a breakpoint on the switch().
With my code I can read a message on the server and write from the client. But I am not being able to write a response from the server and read in the client.
The code on the client
var cli = new TcpClient();
cli.Connect("127.0.0.1", 6800);
string data = String.Empty;
using (var ns = cli.GetStream())
{
using (var sw = new StreamWriter(ns))
{
sw.Write("Hello");
sw.Flush();
//using (var sr = new StreamReader(ns))
//{
// data = sr.ReadToEnd();
//}
}
}
cli.Close();
The code on the server
tcpListener = new TcpListener(IPAddress.Any, port);
tcpListener.Start();
while (run)
{
var client = tcpListener.AcceptTcpClient();
string data = String.Empty;
using (var ns = client.GetStream())
{
using (var sr = new StreamReader(ns))
{
data = sr.ReadToEnd();
//using (var sw = new StreamWriter(ns))
//{
// sw.WriteLine("Hi");
// sw.Flush();
//}
}
}
client.Close();
}
How can I make the server reply after reading the data and make the client read this data?
Since you are using
TcpClient client = tcpListener.AcceptTcpClient();
, you can write back to the client directly without needing it to self-identify. The code you have will actually work if you use Stream.Read() or .ReadLine() instead of .ReadToEnd(). ReadToEnd() will block forever on a network stream, until the stream is closed. See this answer to a similar question, or from MSDN,
ReadToEnd assumes that the stream
knows when it has reached an end. For
interactive protocols in which the
server sends data only when you ask
for it and does not close the
connection, ReadToEnd might block
indefinitely because it does not reach
an end, and should be avoided.
If you use ReadLine() at one side, you will need to use WriteLine() - not Write() - at the other side. The alternative is to use a loop that calls Stream.Read() until there is nothing left to read. You can see a full example of this for the server side in the AcceptTcpClient() documentation on MSDN. The corresponding client example is in the TcpClient documentation.
Cheesy, inneficient, but does the trick on a one-time throwaway program:
Client: In the stream, include the port and IP address it wishes to receive the response from.
Client: Create a listener for that
port and IP.
Server: Read in the port/IP info and
in turn connect, then send the reply
stream.
However, this is a great place to start, look into Sockets class for proper bi-directional communication.