I'm currently working on asynchronous TCP program but I'm having the following issue:
-When the Server sends some stream , the Client first receives an empty buffer and then it receives the stream.
-After the first stream sending,if I'm sending another stream the client's buffer contains the first stream sent and the current
stream.
-If I'm sending another stream, the buffer will contain the stream I sent before and the current one..and so on..
This is really annoying and I don't know where's the problem.
Here is my CLIENT Code:
Socket CLIENT;
byte[] _buffer;
private void button1_Click(object sender, EventArgs e)
{
Start();
}
void Start()
{
CLIENT = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
CLIENT.BeginConnect(IPAddress.Parse("the IPaddress"), 1234, new AsyncCallback(ConnectionCallBack), null);
}
private void ConnectionCallBack(IAsyncResult ar)
{
try
{
CLIENT.EndConnect(ar);
_buffer = new byte[CLIENT.ReceiveBufferSize];
CLIENT.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallBack), null);
}
catch (Exception Er)
{
MessageBox.Show("[[[[ERROR:1]]]]=>" + Er.Message);
}
}
private void ReceiveCallBack(IAsyncResult ar)
{
try
{
int lenght = CLIENT.EndReceive(ar);
if (lenght == 0) { return; }
Array.Resize(ref _buffer, lenght);
string stream = ASCIIEncoding.ASCII.GetString(_buffer);
Array.Resize(ref _buffer, CLIENT.ReceiveBufferSize);
CLIENT.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallBack), null);
}
catch (Exception ex) { MessageBox.Show("[[[[hoERROR:2]]]]=>" + ex.Message); }
}
Here is the server:
private void button2_Click(object sender, EventArgs e)
{
try
{
Socket socket = (Socket)listW.SelectedItems[0].Tag; //contains the socket
socket.BeginSend(_buffer,0,_buffer.Length,SocketFlags.None,new AsyncCallback(SendingCallBack),socket);
ServerSocket.BeginAccept(new AsyncCallback(AcceptCallBack),null);
}
catch (Exception er) { MessageBox.Show("[[[[ERROR:]]]]=>" + er.ToString()); }
}
private void SendingCallBack(IAsyncResult ar)
{
try
{
Socket socket = (Socket)ar.AsyncState;
_buffer = ASCIIEncoding.ASCII.GetBytes(tx1.Text);
socket.BeginSend(_buffer, 0, _buffer.Length, SocketFlags.None, new AsyncCallback(FinalCallBack),socket);
}
catch (Exception er) { MessageBox.Show("[[[[ERROR:3]]]]=>" + er.ToString()); }
}
private void Final(IAsyncResult ar)
{
Socket client = ar.AsyncState as Socket;
client.EndSend(ar);
}
I think you have a few problems. One seems to be the stream in ReceiveCallback. You get a string from the buffer then do nothing with it. Resizing your buffer down then resizing if back up to the original size seems like a waste. Might was well make a copy of the data then call GetString and you can leave your buffer alone.
In your server, you call BeginSend to send _buffer, when that completes you call BeginSend again in SendingCallback with the binary representation of tx1.Text but you don't call EndSend, when that completes you call EndSend on the 2nd BeginSend; but still haven't called it for the 1st.
Related
I have a WPF 'server' app using a socket, with a UWP 'client' app using StreamSocket. I can transfer small amounts of data fine, but if I try and send a 288kb file, the file is received fine by the WPF app but the UWP app never receives the response.
WPF code:
In the ReadCallback method, the content is sent in the format of command;printername{data}. The data is all received fine but the Send method called before processing the data is not received.
public void Start()
{
Task.Run(() =>
{
var ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
var ipAddress = ipHostInfo.AddressList.FirstOrDefault(x =>x.AddressFamily == AddressFamily.InterNetwork);
var localEndPoint = new IPEndPoint(ipAddress, Settings.Default.PrintPort);
listener = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
try
{
listener.Bind(localEndPoint);
listener.Listen(100);
IsRunning = true;
while (true)
{
// Set the event to nonsignaled state.
AllDone.Reset();
// Start an asynchronous socket to listen for connections.
listener.BeginAccept(
AcceptCallback,
listener);
// Wait until a connection is made before continuing.
AllDone.WaitOne();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
});
}
public void AcceptCallback(IAsyncResult ar)
{
if(!IsRunning) return;
// Signal the main thread to continue.
AllDone.Set();
// Get the socket that handles the client request.
Socket handler = listener.EndAccept(ar);
// Create the state object.
StateObject state = new StateObject {WorkSocket = handler};
handler.BeginReceive(state.Buffer, 0, StateObject.BufferSize, 0,
ReadCallback, state);
}
public static void ReadCallback(IAsyncResult ar)
{
try
{
// Retrieve the state object and the handler socket
// from the asynchronous state object.
StateObject state = (StateObject)ar.AsyncState;
Socket handler = state.WorkSocket;
// Read data from the client socket.
int bytesRead = handler.EndReceive(ar);
if (bytesRead > 0)
{
// There might be more data, so store the data received so far.
state.Sb.Append(Encoding.ASCII.GetString(
state.Buffer, 0, bytesRead));
// Check for end-of-file tag. If it is not there, read
// more data.
var content = state.Sb.ToString();
if (content.IndexOf("<EOF>") > -1)
{
content = content.Remove(content.IndexOf("<EOF>"));
if (content.StartsWith("PrintFile"))
{
if (!content.Contains("{"))
{
Send(handler, "false");
return;
}
var parts = content.Substring(0, content.IndexOf('{')).Split(';');
if (string.IsNullOrEmpty(parts[1]))
{
Send(handler, "false");
return;
}
// This send never gets received
Send(handler, "true");
//But the file is printed
var base64 = content.Substring(content.IndexOf('{') + 1);
base64 = base64.Remove(base64.LastIndexOf('}'));
var doc = new Spire.Pdf.PdfDocument(Convert.FromBase64String(base64));
doc.PrintSettings.PrinterName = parts[1];
doc.Print();
}
}
else
{
// Not all data received. Get more.
handler.BeginReceive(state.Buffer, 0, StateObject.BufferSize, 0,
ReadCallback, state);
}
}
}
catch
{
//Ignore
}
}
private static void Send(Socket handler, String data)
{
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.ASCII.GetBytes(data);
// Begin sending the data to the remote device.
handler.BeginSend(byteData, 0, byteData.Length, 0,
SendCallback, handler);
}
private static void SendCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket handler = (Socket)ar.AsyncState;
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
UWP Code:
public bool PrintFlle(string printer, string base64)
{
try
{
var result = Send($"PrintFile;{printer}{{{base64}}}<EOF>").Result;
return bool.TryParse(result, out var b) && b;
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
finally
{
socket.Dispose();
}
}
private async Task<string> Send(string input)
{
try
{
socket = new StreamSocket();
await socket.ConnectAsync(HostName, App.LocalSettings.Values["PrintPort"] as string);
using (Stream outputStream = socket.OutputStream.AsStreamForWrite())
{
using (var streamWriter = new StreamWriter(outputStream))
{
await streamWriter.WriteLineAsync(input);
await streamWriter.FlushAsync();
}
}
using (Stream inputStream = socket.InputStream.AsStreamForRead())
{
using (StreamReader streamReader = new StreamReader(inputStream))
{
var output = await streamReader.ReadLineAsync();
socket.Dispose();
return output;
}
}
}
catch (Exception e)
{
socket.Dispose();
return "";
}
}
I want to send some images from server to client. I want when user connect to server and request for images, i sent some images to that. I searched but all of answers about send one image from client to server not server to client!
I wrote below code for send one image from server to client, but i get below error in runtime, because i shutdown socket and then called 'SendCallback' method. Where i shutdown and close socket?
public class ImageSocketServer
{
public class StateObject
{
// Client socket.
public Socket WorkSocket = null;
// Size of receive buffer.
public const int BufferSize = 256;
// Receive buffer.
public byte[] Buffer = new byte[BufferSize];
// Received data string.
public StringBuilder sb = new StringBuilder();
}
public ManualResetEvent AllDone = new ManualResetEvent(false);
private static ManualResetEvent sendDone = new ManualResetEvent(false);
private Socket handler;
public void StartListening(string ip, int port)
{
IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse(ip), port);
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
listener.Bind(serverEndPoint);
listener.Listen(port);
while (true)
{
AllDone.Reset();
listener.BeginAccept(AcceptCallback, listener);
AllDone.WaitOne();
}
}
private void AcceptCallback(IAsyncResult asyncResult)
{
AllDone.Set();
Socket listener = (Socket)asyncResult.AsyncState;
Socket handler = listener.EndAccept(asyncResult);
StateObject state = new StateObject { WorkSocket = handler };
handler.BeginReceive(state.Buffer, 0, StateObject.BufferSize, 0,
ReadCallback, state);
}
private void ReadCallback(IAsyncResult asyncResult)
{
string content = string.Empty;
StateObject state = (StateObject)asyncResult.AsyncState;
handler = state.WorkSocket;
int bytesRead = handler.EndReceive(asyncResult);
if (bytesRead > 0)
{
state.sb.Append(Encoding.UTF8.GetString(state.Buffer, 0, bytesRead));
content = state.sb.ToString();
if (content.IndexOf(Cache.EndOfMessage, StringComparison.Ordinal) > -1)
{
//Send(handler, #"C:\Users\f.hashemian\Pictures\Camera Roll\test.jpg");
SendImage(handler, #"C:\Users\f.hashemian\Pictures\Camera Roll\test.jpg");
//
}
else
{
handler.BeginReceive(state.Buffer, 0, StateObject.BufferSize, 0, ReadCallback, state);
}
}
}
private void SendImage(Socket client, string imagePath)
{
byte[] imgBuff = File.ReadAllBytes(imagePath);
var length = imgBuff.Length;
Send(client, BitConverter.GetBytes(length));
sendDone.WaitOne();
Send(client, imgBuff);
sendDone.WaitOne();
//Here close connection and i have error in SendCallback
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
private void Send(Socket client, byte[] byteData)
{
// Begin sending the data to the remote device.
client.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), client);
}
private void SendCallback(IAsyncResult asyncResult)
{
try
{
Socket handler = (Socket)asyncResult.AsyncState;
int byteSent = handler.EndSend(asyncResult);
sendDone.Set();
//
}
catch (Exception ex)
{
throw ex;
}
}
}
This is about send one image with send size of image and then send image to client. If you have any tutorial about some images, please send link here
According to MSDN documentation https://learn.microsoft.com/en-us/dotnet/api/system.threading.manualresetevent.set?view=netframework-1.1#System_Threading_ManualResetEvent_Set, you should call Reset() method after calling WaitOne() on ManualResetEvent to set it in nonsignaled state.
private void SendImage(Socket client, string imagePath)
{
byte[] imgBuff = File.ReadAllBytes(imagePath);
var length = imgBuff.Length;
Send(client, BitConverter.GetBytes(length));
sendDone.WaitOne();
sendDone.Reset();
Send(client, imgBuff);
sendDone.WaitOne();
sendDone.Reset();
//Here close connection and i have error in SendCallback
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
Otherwise, the second WaitOne() will be skipped (since the event is in signaled state) and the Shutdown() method will be called. As a result, you will receive an exception in SendCallback, because the connection is already closed. In your case, it is better to use AutoResetEvent https://learn.microsoft.com/en-us/dotnet/api/system.threading.autoresetevent?view=netframework-4.8 which resets automatically after releasing a single waiting thread.
I've been stuck on a problem for some time now, when sending a request from client to server, the server responds with data pulled from sql database and client receives it, everything going fine. The problem is when the client again asks for data from server, which gives me following error: Objectreference not set to an instance of object. Thing is, when adding data to my database, the server can receive multiple requests. According to my try catches, the error occurs when my SendCallback calls my method to start receive data.
private static void BeginAccept()
{
listener.Listen(5);
Thread t = new Thread(() =>
listener.BeginAccept(new AsyncCallback(AcceptCallback), listener));
t.Start();
}
private static void AcceptCallback(IAsyncResult ar)
{
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
handler.BeginReceive(recBuf, 0, bufsize, 0, new AsyncCallback(ReceiveCallback), handler);
Console.WriteLine("client connected" );
}
private static void ReceiveCallback(IAsyncResult ar)
{
try
{
Console.WriteLine("Waiting for data...");
string content = string.Empty;
string[] pieces = null;
string[] delimiters = { "|" };
/*StateObject state = (StateObject)ar.AsyncState; */// Calling the socket from AcceptCallback.
Socket handler = (Socket)ar.AsyncState;
sb.Clear();
int dataReceived = handler.EndReceive(ar);
if (dataReceived > 0)
{
sb.Append(Encoding.ASCII.GetString(recBuf, 0,dataReceived));
if (content.IndexOf("<!ReqDB>") > -1)
{
try
{
Console.WriteLine("Following data received: " + content);
pieces = null;
pieces = content.Split(delimiters, StringSplitOptions.None);
sb = null;
Console.WriteLine("ReqDB received!!");
Int64 ID = Int64.Parse(pieces[0]);
RetrieveDataFromDB(handler, ID);
//Some other irrelevant code....
RetrieveDataFromDB pulls data out of the database, converts it and calls Send(handler, data);
private static void Send(Socket handler, string data)
{
byte[] byteData = Encoding.ASCII.GetBytes(data);
handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), handler);
}
private static void SendCallback(IAsyncResult ar)
{
try
{
Socket handler = (Socket)ar.AsyncState;
byte[] buffer = new byte[1024];
int bytesSend = handler.EndSend(ar);
handler.BeginReceive(recBuf, 0, bufsize, 0, new AsyncCallback(ReceiveCallback), handler);
}
catch (Exception e)
{
Console.WriteLine("Line 197: "+e.ToString());
}
}
Somewhere, probably when SendCallback executes handler.beginReceive and the method is called, the error occurs, and I do not know where the error is, or what is causing the error. I assume it is the handler, though I do not understand why it's causing it.
I used to write socket programs in C and can't understand why the above is happening.
My server blocks at a Receive call, when it returns 0, I break out of the while loop and shutdown the thread.
public class MyServer {
public MyServer() {
}
public void Init() {
ThreadPool.QueueUserWorkItem(StartListening);
while (true) {
Console.Read();
}
}
public void StartListening(Object state) {
// Establish the local endpoint for the socket.
IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 11000);
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try {
// Bind the socket to the local endpoint and listen for incoming connections.
listener.Bind(localEndPoint);
listener.Listen(100);
while (true) {
Console.WriteLine("Waiting for a connection...");
// get connection
Socket client = listener.Accept();
// push client to another thread
ThreadPool.QueueUserWorkItem(HandleClient, client);
}
} catch (Exception e) {
Console.WriteLine(e.ToString());
}
}
private void HandleClient(Object obj) {
// Get the socket that handles the client request.
Socket client = (Socket)obj;
// Create the state object.
StateObject state = new StateObject();
state.workSocket = client;
try {
while (true) {
int bytesRead = client.Receive(state.buffer);
Console.WriteLine("bytesRead=" + bytesRead);
// remote dc.
if (bytesRead == 0)
break;
String content = Encoding.ASCII.GetString(state.buffer, 0, bytesRead);
Console.WriteLine("Read {0} bytes from socket. \n Data : {1}", content.Length, content);
client.Send(state.buffer, 0, state.buffer.Length, 0);
}
} catch (SocketException e) {
Console.WriteLine("SocketException : {0}", e.ToString());
}
client.Shutdown(SocketShutdown.Both);
client.Close();
}
private void Send(Socket handler, String data) {
byte[] byteData = Encoding.ASCII.GetBytes(data);
// Begin sending the data to the remote device.
//handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), handler);
}
}
However, when I click on the close button ("x") of the client, server's Receive call throws a SocketException. According to MSDN's Remarks section, this shouldn't happen because I've satisfied both the connection-oriented part (see above) and client shutdown part(see below) conditions.
Client.cs (pseudo):
public class MyClient {
public void Init() {
byte[] bytes = new byte[1024];
Socket sender = null;
try {
IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
IPEndPoint remoteEP = new IPEndPoint(ipAddress, 11000);
sender = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
sender.Connect(remoteEP);
Console.WriteLine("Socket connected to {0}",
sender.RemoteEndPoint.ToString());
while (true) {
// Encode the data string into a byte array.
String input = Console.ReadLine();
byte[] msg = Encoding.ASCII.GetBytes(input);
// Send the data through the socket.
int bytesSent = sender.Send(msg);
// Receive the response from the remote device.
int bytesRec = sender.Receive(bytes);
Console.WriteLine("Echoed test = {0}",
Encoding.ASCII.GetString(bytes, 0, bytesRec));
}
} catch (ArgumentNullException ane) {
Console.WriteLine("ArgumentNullException : {0}", ane.ToString());
} catch (SocketException se) {
Console.WriteLine("SocketException : {0}", se.ToString());
} catch (Exception e) {
Console.WriteLine("Unexpected exception : {0}", e.ToString());
} finally {
sender.Shutdown(SocketShutdown.Both);
sender.Close();
}
}
}
My shallow understanding of finally blocks is that it will always execute. But it doesn't seem to be the case here.
SO, what did I do wrong here? Should I just catch the exception, close the client socket on the server side and just move on, ignoring it? But I would prefer if an exception were not thrown at all.
I'm working on a chat/IM system for my game (which is written in Flex) and wanted to connect it to my server (which is written in C#) via sockets.
So, I've successfully connected them together using XMLSocket on Flex, and Socket on the server side, the client gets a connected event, sends data correctly, but when I try to send back data from the server to the client, nothing happens (even though the BeginSend callback shows that the entire buffer was sent).
Client:
private var hostName:String = "localhost";
private var port:uint = 4444;
private var socket:XMLSocket;
public var app:DotNETServerTest;
public function DotNetSocketExample() {
socket = new XMLSocket();
configureListeners(socket);
socket.connect(hostName, port);
}
public function send(data:Object):void {
socket.send(data);
}
public function disconnect():void {
socket.close();
closeHandler(null);
}
private function configureListeners(dispatcher:IEventDispatcher):void {
dispatcher.addEventListener(Event.CLOSE, closeHandler);
dispatcher.addEventListener(Event.CONNECT, connectHandler);
dispatcher.addEventListener(DataEvent.DATA, dataHandler);
}
private function closeHandler(event:Event):void {
trace("closeHandler: " + event);
app.send_btn.enabled = false;
app.disconnect_btn.enabled = false;
}
private function connectHandler(event:Event):void {
trace("connectHandler: " + event);
app.send_btn.enabled = true;
app.disconnect_btn.enabled = true;
}
private function dataHandler(event:DataEvent):void {
trace("dataHandler: " + event);
Alert.show(event.data);
}
Server (Only specific parts):
// This is the call back function, which will be invoked when a client is connected
public static void OnClientConnect(IAsyncResult asyn)
{
try
{
SocketClient NewConnection = new SocketClient(SocketServer.EndAccept(asyn));
// This is a test message I'm attempting to send
SendMessageTo(NewConnection, "<test></test>");
Clients.Add(NewConnection);
WaitForData(NewConnection);
LogMessage(NewConnection, "Client # {0} connected", Clients.Count);
SocketServer.BeginAccept(new AsyncCallback(OnClientConnect), null);
}
catch (ObjectDisposedException)
{
LogMessage("OnClientConnection: Socket has been closed.");
}
catch (SocketException se)
{
Console.WriteLine(se.Message);
}
}
internal static void SendMessageTo(SocketClient client, string Data)
{
byte[] byteData = Encoding.ASCII.GetBytes(Data);
SendMessageTo(client, byteData);
}
internal static void SendMessageTo(SocketClient client, byte[] byteData)
{
try
{
client.socket.BeginSend(byteData, 0, byteData.Length, SocketFlags.None, new AsyncCallback(SendCallback), client);
}
catch (Exception e)
{
LogMessage(client, "Error sending data to client: {0}", e.Message);
}
}
internal static void SendCallback(IAsyncResult ar)
{
// Retrieve the socket from the async state object.
SocketClient handler = (SocketClient)ar.AsyncState;
try
{
int bytesSent = handler.socket.EndSend(ar);
}
catch (Exception e)
{
LogMessage(handler, e.Message);
}
}
Please help!
Thanks, Ron
Found the problem - I didn't send out \0 at the end of each send.
Changed this:
byte[] byteData = Encoding.ASCII.GetBytes(Data);
client.socket.BeginSend(byteData, 0, byteData.Length, SocketFlags.None, new AsyncCallback(SendCallback), client);
To this:
byte[] byteData = Encoding.ASCII.GetBytes(Data + "\0");
client.socket.BeginSend(byteData, 0, byteData.Length, SocketFlags.None, new AsyncCallback(SendCallback), client);