I am making a little game. Server on C++ and client based on C#. I have problems with data receiving, I dont properly understand how it works, do I need second socket to receive? Or the first socket connect and usable for receiving at the same time? This is the client
public class Connection
{
static private string ip = "127.0.0.1";
static private int port = 54000;
static Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// static Socket acpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
public static void connectToServer()
{
socket.Connect(ip, port);
}
public static void sendData(byte[] buffer)
{
socket.Send(buffer);
}
public static byte[] encodeMessage(string message)
{
byte[] bf = Encoding.ASCII.GetBytes(message);
return bf;
}
public static void recvData()
{
byte[] buf = new byte[256];
byte[] copy = new byte[256];
try
{
socket.Receive(buf);
}
catch (Exception e)
{
Console.WriteLine("Error");
}
if (buf != copy)
{
Console.WriteLine(Encoding.ASCII.GetChars(buf).ToString());
buf = copy;
}
}
}
And this is the server:
int main() {
//init sock
WSADATA wsData;
WORD ver = MAKEWORD(2, 2);
int wsok = WSAStartup(ver, &wsData);
if (wsok != 0) {
cerr << "Error while init\n";
return 0;
}
//create
SOCKET listening = socket(AF_INET, SOCK_STREAM, 0);
if (listening == INVALID_SOCKET) {
cerr << "Error while creating\n";
return 0;
}
//bind
sockaddr_in hint;
hint.sin_family = AF_INET;
hint.sin_port = htons(54000);
hint.sin_addr.S_un.S_addr = INADDR_ANY;
bind(listening, (sockaddr*)&hint, sizeof(hint));
//tell winsock that the socket is for listen
listen(listening, SOMAXCONN);
fd_set master;
FD_ZERO(&master);
FD_SET(listening, &master);
while (true) {
fd_set copy = master;
int socketCount = select(0, ©, nullptr, nullptr, nullptr);
for (int i = 0; i < socketCount; i++) {
SOCKET sock = copy.fd_array[i];
if (sock == listening) {
//accept connection
SOCKET client = accept(listening, nullptr, nullptr);
//add connection to list(&master)
FD_SET(client, &master);
//send welcome msg to connected client
string welcomeMsg = "Your connected!";
send(client, welcomeMsg.c_str(), welcomeMsg.size() + 1, 0);
}
else{
//accept message
char buf[32];
ZeroMemory(buf, 32);
string str;
int cnt = 0;
int bytesIn = recv(sock, buf, 32, 0);
for (int i = 0; i < sizeof(buf); i++) {
if (buf[i] != '0') {
content[cnt] = buf[i];
cnt++;
}
}
if (bytesIn <= 0) {
closesocket(sock);
FD_CLR(sock, &master);
}
else {
for (int i = 0; i < sizeof(buf); i++) {
cout << content[i];
}
for (int i = 0; i < master.fd_count; i++) {
SOCKET outSock = master.fd_array[i];
if (outSock != listening && outSock != sock) {
send(outSock, content, cnt, 0);
cout << "Message Send..." << endl;
}
}
}
}
}
}
And I have timer where i call recvData(). The problem is that After connection it returns "You're Connected!" but after that it just stuck, doesn't work. If i comment the Socket.Receive I have no problem, but i need this receiving. Thanks
You don't have to use a second socket to receive data, but Send and Receive are synchronous functions, so the thread is blocked until the current operation finishes doing its job. For receiving, the socket has to receive at least on byte in order to unblock the application. If no data is available, Receive will wait indefinitely unless you specify a timeout using ReceiveTimeout property.
To avoid the blocking part, use the asynchronous functions BeginReceive and BeginSend. MSDN has a full server - client example using asynchronous sockets.
Related
Receiving data from GPS Device:
I have a TCP server setup which is receiving data from various GPS Trackers (GT06). Each GPS devices initiates the request, server accepts it, and starts receiving NMEA data.
Problem Is when GPS Connect to Server Error:"An existing connection was forcibly closed by the remote host"
The problem is that I don't know how to receive data from GPS over GPRS/TCP connection.
Any suggestions?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace T1
{
class Program
{
public class StateObject
{
public const int DEFAULT_SIZE = 1024; //size of receive buffer
public byte[] buffer = new byte[DEFAULT_SIZE]; //receive buffer
public int dataSize = 0; //data size to be received
public bool dataSizeReceived = false; //received data size?
public StringBuilder sb = new StringBuilder(); //received data String
public int dataRecieved = 0;
public Socket workSocket = null; //client socket.
public DateTime TimeStamp; //timestamp of data
public const int BufferSize = 256;
} //end class StateObject
public static AutoResetEvent allDone = new AutoResetEvent(false);
public static AutoResetEvent acceptDone = new AutoResetEvent(false);
static void Main(string[] args)
{
StartListening();
}
public static void StartListening()
{
// Data buffer for incoming data.
byte[] bytes = new Byte[1024];
// Establish the local endpoint for the socket.
// The DNS name of the computer
// running the listener is "host.contoso.com".
IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
IPAddress ipAddress = ipHostInfo.AddressList[0];
IPAddress local = IPAddress.Parse("103.118.16.129");
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 8821);
// Create a TCP/IP socket.
Socket listener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
// Bind the socket to the local endpoint and listen for incoming connections.
try
{
listener.Bind(localEndPoint);
listener.Listen(100);
while (true)
{
// Set the event to nonsignaled state.
allDone.Reset();
// Start an asynchronous socket to listen for connections.
Console.WriteLine("Waiting for a connection...");
listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
// Wait until a connection is made before continuing.
allDone.WaitOne();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
// Console.WriteLine("\nPress ENTER to continue...");
// Console.Read();
}
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,
new AsyncCallback(SendCallback), handler);
}
private static void Send(Socket handler, byte[] 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(data, 0, data.Length, 0,
new AsyncCallback(SendCallback), handler);
}
private static void SendCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket handler = (Socket)ar.AsyncState;
// Complete sending the data to the remote device.
int bytesSent = handler.EndSend(ar);
Console.WriteLine("Sent {0} bytes to client.", bytesSent);
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
public static void AcceptCallback(IAsyncResult ar)
{
// Signal the main thread to continue.
allDone.Set();
// Get the socket that handles the client request.
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
// Create the state object.
StateObject state = new StateObject();
state.workSocket = handler;
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
static byte[] Unpack(string data)
{
//return null indicates an error
List<byte> bytes = new List<byte>();
// check start and end bytes
if ((data.Substring(0, 4) != "7878") && (data.Substring(data.Length - 4) != "0D0A"))
{
return null;
}
for (int index = 4; index < data.Length - 4; index += 2)
{
bytes.Add(byte.Parse(data.Substring(index, 2), System.Globalization.NumberStyles.HexNumber));
}
//crc test
byte[] packet = bytes.Take(bytes.Count - 2).ToArray();
byte[] crc = bytes.Skip(bytes.Count - 2).ToArray();
uint CalculatedCRC = crc_bytes(packet);
return packet;
}
static public UInt16 crc_bytes(byte[] data)
{
ushort crc = 0xFFFF;
for (int i = 0; i < data.Length; i++)
{
crc ^= (ushort)(Reflect(data[i], 8) << 8);
for (int j = 0; j < 8; j++)
{
if ((crc & 0x8000) > 0)
crc = (ushort)((crc << 1) ^ 0x1021);
else
crc <<= 1;
}
}
crc = Reflect(crc, 16);
crc = (ushort)~crc;
return crc;
}
static public ushort Reflect(ushort data, int size)
{
ushort output = 0;
for (int i = 0; i < size; i++)
{
int lsb = data & 0x01;
output = (ushort)((output << 1) | lsb);
data >>= 1;
}
return output;
}
public static void ReadCallback(IAsyncResult ar)
{
String content = String.Empty;
// 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)
{
if (state.buffer[3] == 1)
{
string input = BitConverter.ToString(state.buffer, 0, bytesRead).Replace("-", "");
Console.WriteLine("Recived {0} bytes to client.", input);
//byte[] bytes = Unpack(input);
//byte[] serialNumber = bytes.Skip(bytes.Length - 2).ToArray();
//byte[] response = { 0x78, 0x78, 0x05, 0x01, 0x00, 0x00, 0x00, 0x0 };
//serialNumber.CopyTo(response, 4);
//UInt16 sendCRC = crc_bytes(response.Take(response.Length - 2).ToArray());
//response[response.Length - 2] = (byte)((sendCRC >> 8) & 0xFF);
//response[response.Length - 1] = (byte)((sendCRC) & 0xFF);
//Send(handler, response);
// handler.Send(response);
}
else
{
// 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.
// content = state.sb.ToString();
Console.WriteLine("Recived {0} bytes to client.", Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
// SaveData(content);
// Not all data received. Get more.
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
// }
}
}
}
}
}
#jdweng
Sir I try your Suggestion But Same problem Not Receiving any Message.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
namespace T1
{
internal class Program
{
public class StateObject
{
public const int DEFAULT_SIZE = 1024; //size of receive buffer
public byte[] buffer = new byte[DEFAULT_SIZE]; //receive buffer
public int dataSize = 0; //data size to be received
public bool dataSizeReceived = false; //received data size?
public StringBuilder sb = new StringBuilder(); //received data String
public int dataRecieved = 0;
public Socket workSocket = null; //client socket.
public DateTime TimeStamp; //timestamp of data
public const int BufferSize = 256;
} //end class StateObject
public static AutoResetEvent allDone = new AutoResetEvent(false);
public static AutoResetEvent acceptDone = new AutoResetEvent(false);
private static void Main(string[] args)
{
Write_log("StartListening");
StartListening();
}
public static void StartListening()
{
// Data buffer for incoming data.
byte[] bytes = new Byte[1024];
// Establish the local endpoint for the socket.
IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, 8821);
// Create a TCP/IP socket.
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// Bind the socket to the local endpoint and listen for incoming connections.
try
{
listener.Bind(localEndPoint);
listener.Listen(100);
// Set the event to nonsignaled state.
allDone.Reset();
// Start an asynchronous socket to listen for connections.
Console.WriteLine("Waiting for a connection...");
Write_log("Waiting for a connection...");
listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
// Wait until a connection is made before continuing.
allDone.WaitOne();
Write_log("allDone");
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
// Console.WriteLine("\nPress ENTER to continue...");
// Console.Read();
}
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,
new AsyncCallback(SendCallback), handler);
}
private static void Send(Socket handler, byte[] 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(data, 0, data.Length, 0, new AsyncCallback(SendCallback), handler);
}
private static void SendCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket handler = (Socket)ar.AsyncState;
// Complete sending the data to the remote device.
int bytesSent = handler.EndSend(ar);
Console.WriteLine("Sent {0} bytes to client.", bytesSent);
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
public static void AcceptCallback(IAsyncResult ar)
{
// Signal the main thread to continue.
allDone.Set();
// Get the socket that handles the client request.
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
// Create the state object.
StateObject state = new StateObject();
state.workSocket = handler;
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
Write_log("ReadCallback...");
}
private static byte[] Unpack(string data)
{
//return null indicates an error
List<byte> bytes = new List<byte>();
// check start and end bytes
if ((data.Substring(0, 4) != "7878") && (data.Substring(data.Length - 4) != "0D0A"))
{
return null;
}
for (int index = 4; index < data.Length - 4; index += 2)
{
bytes.Add(byte.Parse(data.Substring(index, 2), System.Globalization.NumberStyles.HexNumber));
}
//crc test
byte[] packet = bytes.Take(bytes.Count - 2).ToArray();
byte[] crc = bytes.Skip(bytes.Count - 2).ToArray();
uint CalculatedCRC = crc_bytes(packet);
return packet;
}
static public UInt16 crc_bytes(byte[] data)
{
ushort crc = 0xFFFF;
for (int i = 0; i < data.Length; i++)
{
crc ^= (ushort)(Reflect(data[i], 8) << 8);
for (int j = 0; j < 8; j++)
{
if ((crc & 0x8000) > 0)
crc = (ushort)((crc << 1) ^ 0x1021);
else
crc <<= 1;
}
}
crc = Reflect(crc, 16);
crc = (ushort)~crc;
return crc;
}
static public ushort Reflect(ushort data, int size)
{
ushort output = 0;
for (int i = 0; i < size; i++)
{
int lsb = data & 0x01;
output = (ushort)((output << 1) | lsb);
data >>= 1;
}
return output;
}
public static void ReadCallback(IAsyncResult ar)
{
String content = String.Empty;
// 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);
Write_log(bytesRead.ToString());
if (bytesRead > 0)
{
if (state.buffer[3] == 1)
{
string input = BitConverter.ToString(state.buffer, 0, bytesRead).Replace("-", "");
Console.WriteLine("Recived {0} bytes to client.", input);
//byte[] bytes = Unpack(input);
//byte[] serialNumber = bytes.Skip(bytes.Length - 2).ToArray();
//byte[] response = { 0x78, 0x78, 0x05, 0x01, 0x00, 0x00, 0x00, 0x0 };
//serialNumber.CopyTo(response, 4);
//UInt16 sendCRC = crc_bytes(response.Take(response.Length - 2).ToArray());
//response[response.Length - 2] = (byte)((sendCRC >> 8) & 0xFF);
//response[response.Length - 1] = (byte)((sendCRC) & 0xFF);
//Send(handler, response);
// handler.Send(response);
}
else
{
// 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.
// content = state.sb.ToString();
Console.WriteLine("Recived {0} bytes to client.", Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
// SaveData(content);
// Not all data received. Get more.
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
// }
}
}
}
private static void Write_log(string logx)
{
StringBuilder sb = new StringBuilder();
string rootPath = System.IO.Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName);
sb.Append(logx);
// flush every 20 seconds as you do it
File.AppendAllText(rootPath + "//log.txt", sb.ToString());
sb.Clear();
}
}
}
i have the following code executed by a listening Thread. What it does: Reading the first Message as the total message length then assemble all packets to a big data array. (Im sending images) It all works as intended.
But after the first image is recieved and the function is done. ("ImageLengthResetted" gets printed) It closes the connection. I think this is due the fact i am running out of the scope from:
using(connectedTcpClient = tcpListener.AcceptTcpClient())
and thats what kills the connection. How can i keep this connection open?
Adding another
while(true)
after i've been connected wont do the trick. As well as executing the while loop completle after the using statments.
private void ListenForIncommingRequests()
{
try
{
// Create listener on localhost port 8052.
localAddr = IPAddress.Parse(IPadrr);
Debug.Log(localAddr);
tcpListener = new TcpListener(localAddr, port);
Debug.Log("Before Init tcplistern");
tcpListener.Start();
Debug.Log("Server is listening");
Byte[] dataRecieved = new Byte[SEND_RECIEVE_COUNT];
while (true)
{
using (connectedTcpClient = tcpListener.AcceptTcpClient())
{
Debug.Log("Accepted TCP Client");
// Get a stream object for reading
using (NetworkStream stream = connectedTcpClient.GetStream())
{
int length;
Debug.Log("Accepted Stream");
// Read incomming stream into byte arrary.
while ((length = stream.Read(dataRecieved, 0, dataRecieved.Length)) != 0)
{
Debug.Log("receiving Loop lengt: " + length);
counterReceived++;
//Get Message length with first message
if (messageLength == 0)
{
messageLength = System.BitConverter.ToInt32(dataRecieved, 0);
data = new byte[messageLength];
messageJunks = messageLength / SEND_RECIEVE_COUNT;
restMessage = messageLength % SEND_RECIEVE_COUNT;
junkCounter = 0;
}
else
{
if (junkCounter < messageJunks)
{
Array.Copy(dataRecieved, 0, data, junkCounter * SEND_RECIEVE_COUNT, SEND_RECIEVE_COUNT);
junkCounter++;
}
else
{
Array.Copy(dataRecieved, 0, data, junkCounter * SEND_RECIEVE_COUNT, restMessage);
//Whole Message recieved, reset Message length
messageLength = 0;
readyToDisplay = true;
Debug.Log("ImageLengthResetteed");
}
}
}
}
}
}
}
catch (Exception socketException)
{
Debug.Log("SocketException " + socketException.ToString());
}
}
Client Side opens send Thread with following function where socketConnection gets globally initialized on the receiving thread of the client:
private void sendData(byte[] data)
{
try
{
//socketConnection = new TcpClient(IPadrr, port);
using (NetworkStream stream = socketConnection.GetStream())
{
//Prepare the Length Array and send first
byte[] dataLength = BitConverter.GetBytes(data.Length);
int packagesSend = 0;
int numberPackages = data.Length / SEND_RECIEVE_COUNT;
if (stream.CanWrite)
{
for (counter = 0; counter <= data.Length; counter += SEND_RECIEVE_COUNT)
{
if (counter == 0)
{
stream.Write(dataLength, 0, dataLength.Length);
}
if (packagesSend < numberPackages)
{
stream.Write(data, counter, SEND_RECIEVE_COUNT);
Thread.Sleep(20);
packagesSend++;
}
else
{
stream.Write(data, counter, data.Length % SEND_RECIEVE_COUNT);
Debug.Log("FINDISCHD");
}
}
}
}
}
catch (Exception err)
{
print(err.ToString());
}
}
Im glad for any help!
The Problem was on the Client Side. I initialized the
NetworkStream stream;
now globally in the same function the socketConnection gets init.
I am currently working on a simple udp client/server system, and I stumbled upon the following: When I try to get the IP of IPEndPoint (which I fetched using IPAdress.Any)in a program using UdpClient it works and I get the following result (the top one):
But when I use a normal socket instead of a UdpClient it somehow fails to distinguish the clients/IPs (bottom one). The code for both is listed below. The reason I would like to use sockets is because using the same class for both sending and receiving (not the same instance) is convenient and makes the code far more understandable.
First
bool messageReceived = false;
bool done = false;
const int listenPort = 11000;
UdpClient listener = new UdpClient(listenPort);
IPEndPoint receiveEP = new IPEndPoint(IPAddress.Any, listenPort);
string[] adresses = new string[2];
public void ReceiveCallback(IAsyncResult ar)
{
int id = 0;
Byte[] receiveBytes = listener.EndReceive(ar, ref receiveEP);
for (int i = 0; i < adresses.Length; i++)
{
if (adresses[i] == receiveEP.Address.ToString())
{
id = i;
break;
}
else if (adresses[i] == null)
{
id = i;
adresses[i] = receiveEP.Address.ToString();
break;
}
}
byte[] a= Encoding.ASCII.GetBytes("Is anybody there?");
listener.Send(a, a.Length, receiveEP);
Console.WriteLine("Received message from {0} (client {1}):", adresses[id],id);
string receiveString = Encoding.ASCII.GetString(receiveBytes);
if (receiveString == "stop")
{
done = true;
}
Console.WriteLine("Received: {0}", receiveString);
messageReceived = true;
}
public void ReceiveMessages()
{
Console.WriteLine("listening for messages");
while(!done){
try
{
messageReceived = false;
if (!messageReceived)
{
listener.BeginReceive(new AsyncCallback(ReceiveCallback), null);
}
while (!messageReceived)
{
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
Console.WriteLine("Done receiving messages...");
for (int i = 0; i < adresses.Length; i++)
{
if (adresses[i] != null)
{
Console.WriteLine(adresses[i]);
}
}
Console.ReadLine();
listener.Close();
}'
Second
bool messageReceived = false;
bool done = false;
const int listenPort = 11000;
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
IPEndPoint receiveEP = new IPEndPoint(IPAddress.Any, listenPort);
string[] adresses = new string[2];
byte[] buffer = new byte[1024];
public void ReceiveMessages()
{
listener.Bind(receiveEP);
Console.WriteLine("listening for messages");
while (!done)
{
try
{
messageReceived = false;
if (!messageReceived)
{
listener.BeginReceive(buffer, 0,1024,SocketFlags.None,new AsyncCallback(ReceiveCallback), null);
}
while (!messageReceived)
{
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
Console.WriteLine("Done receiving messages...");
for (int i = 0; i < adresses.Length; i++)
{
if (adresses[i] != null)
{
Console.WriteLine(adresses[i]);
}
}
Console.ReadLine();
listener.Close();
}
public void ReceiveCallback(IAsyncResult ar)
{
int id = 0;
int read = listener.EndReceive(ar);
for (int i = 0; i < adresses.Length; i++)
{
if (adresses[i] == receiveEP.Address.ToString())
{
id = i;
break;
}
else if (adresses[i] == null)
{
id = i;
adresses[i] = receiveEP.Address.ToString();
break;
}
}
Console.WriteLine("Received message from {0} (client {1}):", adresses[id], id);
string receiveString = Encoding.ASCII.GetString(buffer,0,read);
if (receiveString == "stop")
{
done = true;
}
Console.WriteLine("Received: {0}", receiveString);
messageReceived = true;
}'
I've already tried Socket.ReceiveMessageFrom() and using the packetinfo it returned but I ended up with the ip4 of the server even when I send from another machine. Could someone help me out?
Even though this was never supposed to be a Q/A type of question, I've found a way of getting it to work, which means receive() changes the groupEP to the IP of the data packet's sender by just using a Socket instead of an UdpClient (I mimicked the way an UdpClient works). At the moment, it's still synchronous (listener.Receive() is a blocking call) but that will be changed in the near future:
private const int listenPort = 11000;
public static int Main()
{
bool done = false;
Listener listener = new Listener(listenPort);
IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, listenPort);
byte[] buffer = new byte[2048];
string received_data;
try
{
while (!done)
{
Console.WriteLine("Waiting for broadcast");
buffer=listener.Receive(ref groupEP);
received_data = Encoding.ASCII.GetString(buffer);
Console.WriteLine("Received a broadcast from {0}: {1}", groupEP.ToString(), received_data);
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
return 0;
}
}
public class Listener
{
public Socket client;
public AddressFamily adressFamily;
byte[] byte_buffer = new byte[2048];
public int port;
public Listener(int p)
{
port=p;
adressFamily = AddressFamily.InterNetwork;
IPEndPoint localEP;
localEP = new IPEndPoint(IPAddress.Any, port);
client = new Socket(this.adressFamily, SocketType.Dgram, ProtocolType.Udp);
client.Bind(localEP);
}
public byte[] Receive(ref IPEndPoint remoteEP)
{
IPEndPoint ipEndPoint=new IPEndPoint(IPAddress.Any,port);
EndPoint endPoint = (EndPoint)ipEndPoint;
int num = client.ReceiveFrom(byte_buffer, 2048, SocketFlags.None, ref endPoint);
remoteEP = (IPEndPoint)endPoint;
if (num < 2048)
{
byte[] array = new byte[num];
Buffer.BlockCopy(byte_buffer, 0, array, 0, num);
return array;
}
return byte_buffer;
}
I have the the following two scenarios that I am testing and one works but the other does not.
I have socket server and socket client application running on two different machines
both the scenarios are using the socketasynceventargs
Scenario 1 (Works)
create 40k socket clients in a loop, wait for all connections to be established and then all clients send messages to the server at the same time and receive response from the server 10 times(i.e. send/receive happens 10 times).
Scenario 2 (Does not work. I get a lot of connection refusal errors)
create 40k socket clients in a loop and send/receive the same 10 messages to the server as soon as each client is connected instead of waiting for the 40k connections to be established.
I cant figure out why my second scenario would fail. i understand that in scenario 1 the server is not doing much until all the 40k connections are made. but it is able to communicate with all the clients at the same time. any ideas??
Thank you for you patience.
here is the socket server code
public class SocketServer
{
private static System.Timers.Timer MonitorTimer = new System.Timers.Timer();
public static SocketServerMonitor socket_monitor = new SocketServerMonitor();
private int m_numConnections;
private int m_receiveBufferSize;
public static BufferManager m_bufferManager;
Socket listenSocket;
public static SocketAsyncEventArgsPool m_readWritePool;
public static int m_numConnectedSockets;
private int cnt = 0;
public static int Closecalled=0;
public SocketServer(int numConnections, int receiveBufferSize)
{
m_numConnectedSockets = 0;
m_numConnections = numConnections;
m_receiveBufferSize = receiveBufferSize;
m_bufferManager = new BufferManager(receiveBufferSize * numConnections ,
receiveBufferSize);
m_readWritePool = new SocketAsyncEventArgsPool(numConnections);
}
public void Init()
{
MonitorTimer.Interval = 30000;
MonitorTimer.Start();
MonitorTimer.Elapsed += new System.Timers.ElapsedEventHandler(socket_monitor.Log);
m_bufferManager.InitBuffer();
SocketAsyncEventArgs readWriteEventArg;
for (int i = 0; i < m_numConnections; i++)
{
readWriteEventArg = new SocketAsyncEventArgs();
m_readWritePool.Push(readWriteEventArg);
}
}
public void Start(IPEndPoint localEndPoint)
{
listenSocket = new Socket(localEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
listenSocket.Bind(localEndPoint);
listenSocket.Listen(1000);
StartAccept(null);
}
public void Stop()
{
if (listenSocket == null)
return;
listenSocket.Close();
listenSocket = null;
Thread.Sleep(15000);
}
private void StartAccept(SocketAsyncEventArgs acceptEventArg)
{
if (acceptEventArg == null)
{
acceptEventArg = new SocketAsyncEventArgs();
acceptEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(AcceptEventArg_Completed);
}
else
{
// socket must be cleared since the context object is being reused
acceptEventArg.AcceptSocket = null;
}
try
{
bool willRaiseEvent = listenSocket.AcceptAsync(acceptEventArg);
if (!willRaiseEvent)
{
ProcessAccept(acceptEventArg);
}
}
catch (Exception e)
{
}
}
void AcceptEventArg_Completed(object sender, SocketAsyncEventArgs e)
{
ProcessAccept(e);
}
private void ProcessAccept(SocketAsyncEventArgs e)
{
Interlocked.Increment(ref m_numConnectedSockets);
socket_monitor.IncSocketsConnected();
SocketAsyncEventArgs readEventArgs = m_readWritePool.Pop();
m_bufferManager.SetBuffer(readEventArgs);
readEventArgs.UserToken = new AsyncUserToken { id = cnt++, StarTime = DateTime.Now };
readEventArgs.AcceptSocket = e.AcceptSocket;
SocketHandler handler=new SocketHandler(readEventArgs);
StartAccept(e);
}
}
class SocketHandler
{
private SocketAsyncEventArgs _socketEventArgs;
public SocketHandler(SocketAsyncEventArgs socketAsyncEventArgs)
{
_socketEventArgs = socketAsyncEventArgs;
_socketEventArgs.Completed += new EventHandler<SocketAsyncEventArgs>(IO_Completed);
StartReceive(_socketEventArgs);
}
private void StartReceive(SocketAsyncEventArgs receiveSendEventArgs)
{
bool willRaiseEvent = receiveSendEventArgs.AcceptSocket.ReceiveAsync(receiveSendEventArgs);
if (!willRaiseEvent)
{
ProcessReceive(receiveSendEventArgs);
}
}
private void ProcessReceive(SocketAsyncEventArgs e)
{
// check if the remote host closed the connection
AsyncUserToken token = (AsyncUserToken)e.UserToken;
//token.StarTime = DateTime.Now;
if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success)
{
// process the data here
//reply to client
byte[] AckData1 = BitConverter.GetBytes(1);
SendData(AckData1, 0, AckData1.Length, e);
StartReceive(e);
}
else
{
CloseClientSocket(e);
}
}
private void IO_Completed(object sender, SocketAsyncEventArgs e)
{
// determine which type of operation just completed and call the associated handler
switch (e.LastOperation)
{
case SocketAsyncOperation.Receive:
ProcessReceive(e);
break;
case SocketAsyncOperation.Send:
ProcessSend(e);
break;
default:
throw new ArgumentException("The last operation completed on the socket was not a receive or send");
}
}
private void CloseClientSocket(SocketAsyncEventArgs e)
{
AsyncUserToken token = e.UserToken as AsyncUserToken;
// close the socket associated with the client
try
{
e.AcceptSocket.Shutdown(SocketShutdown.Send);
}
catch (Exception ex)
{
}
e.AcceptSocket.Close();
Interlocked.Decrement(ref SocketServer.m_numConnectedSockets);
SocketServer.socket_monitor.DecSocketsConnected();
SocketServer.m_bufferManager.FreeBuffer(e);
e.Completed -= new EventHandler<SocketAsyncEventArgs>(IO_Completed);
SocketServer.m_readWritePool.Push(e);
}
public void SendData(Byte[] data, Int32 offset, Int32 count, SocketAsyncEventArgs args)
{
try
{
Socket socket = args.AcceptSocket;
if (socket.Connected)
{
var i = socket.Send(data, offset, count, SocketFlags.None);
}
}
catch (Exception Ex)
{
}
}
}
here is the client code that throws the error in the connectcallback method
// State object for receiving data from remote device.
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 int count = 0;
}
public class AsynchronousClient
{
// The port number for the remote device.
private const int port = 11000;
private static int closecalled = 0;
private static bool wait = true;
// ManualResetEvent instances signal completion.
private static ManualResetEvent connectDone =
new ManualResetEvent(false);
private static ManualResetEvent sendDone =
new ManualResetEvent(false);
private static ManualResetEvent receiveDone =
new ManualResetEvent(false);
// The response from the remote device.
private static String response = String.Empty;
private static void StartClient(Socket client, IPEndPoint remoteEP)
{
// Connect to a remote device.
try
{
// Connect to the remote endpoint.
client.BeginConnect(remoteEP,
new AsyncCallback(ConnectCallback), new StateObject { workSocket = client });
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void ConnectCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
StateObject state = (StateObject)ar.AsyncState;
var client = state.workSocket;
// Complete the connection.
client.EndConnect(ar);
var data = "AA5500C08308353816050322462F01020102191552E7D3FA52E7D3FB1FF85BF1FE9F201000004AB80000000500060800001EFFB72F0D00002973620000800000FFFFFFFF00009D6D00003278002EE16D0000018500000000000000000000003A0000000100000000828C80661FF8B436FE9EA9FC000000120000000700000000000000000000000400000000000000000000000000000000000000000000281E0000327800000000000000000000000000AF967D00000AEA000000000000000000000000";
Send(state, data);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void Receive(StateObject state)
{
try
{
Socket client = state.workSocket;
// Begin receiving the data from the remote device.
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void ReceiveCallback(IAsyncResult ar)
{
try
{
StateObject state = (StateObject)ar.AsyncState;
Socket client = state.workSocket;
// Read data from the remote device.
int bytesRead = client.EndReceive(ar);
//if (wait)
//{
// connectDone.WaitOne();
//}
if (bytesRead > 0)
{
state.count = state.count + 1;
byte[] b = new byte[bytesRead];
Array.Copy(state.buffer, b, 1);
if (b[0] == 1)
{
if (state.count < 10)
{
var data = "AA5500C08308353816050322462F01020102191552E7D3FA52E7D3FB1FF85BF1FE9F201000004AB80000000500060800001EFFB72F0D00002973620000800000FFFFFFFF00009D6D00003278002EE16D0000018500000000000000000000003A0000000100000000828C80661FF8B436FE9EA9FC000000120000000700000000000000000000000400000000000000000000000000000000000000000000281E0000327800000000000000000000000000AF967D00000AEA000000000000000000000000";
Send(state, data);
}
else
{
Interlocked.Increment(ref closecalled);
Console.WriteLine("closecalled:-" + closecalled + " at " + DateTime.Now);
client.Close();
}
}
else
{
// Get the rest of the data.
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state);
}
}
else
{
client.Close();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void Send(StateObject state, String data)
{
try
{
Socket client = state.workSocket;
var hexlen = data.Length;
byte[] byteData = new byte[hexlen / 2];
int[] hexarray = new int[hexlen / 2];
int i = 0;
int k = 0;
//create the byte array
while (i < data.Length / 2)
{
string first = data[i].ToString();
i++;
string second = data[i].ToString();
string x = first + second;
byteData[k] = (byte)Convert.ToInt32(x, 16);
i++;
k++;
}
// Begin sending the data to the remote device.
client.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), state);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void SendCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
StateObject state = (StateObject)ar.AsyncState;
Socket client = state.workSocket;
// Complete sending the data to the remote device.
int bytesSent = client.EndSend(ar);
Receive(state);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
public static int Main(String[] args)
{
Start();
Console.ReadLine();
return 0;
}
private static void Start()
{
IPAddress ipaddress = IPAddress.Parse("10.20.2.152");
IPEndPoint remoteEP = new IPEndPoint(ipaddress, port);
for (int i = 0; i < 40000; i++)
{
Thread.Sleep(1);
// Create a TCP/IP socket.
try
{
Socket client = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
StartClient(client, remoteEP);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
if (i == 39999)
{
Console.WriteLine("made all conns at " + DateTime.Now);
}
}
}
}
I would use a linear queue to accept incoming connections. Something like this:
public async Task Accept40KClients()
{
for (int i = 0; i < 40000; i++)
{
// Await this here -------v
bool willRaiseEvent = await listenSocket.AcceptAsync(acceptEventArg);
if (!willRaiseEvent)
{
ProcessAccept(acceptEventArg);
}
}
}
If that's not fast enough, maybe you can do 10 waits at a time, but I think this is good enough... I might be wrong on this though.
I have a small file transfer application using WCF service, that send files and folders over tcp sockets.My problem that when i cancel the transfer operation (backgroundworker) from the client, the server still freezed on client.Receive, It supposes to give me this exception: An existing connection was forcibly closed by the remote host ,but it doesn't,despite on the client side the listener.Connected becomes false and socket.Connected becomes false
I need to get this exception and handle it so i can close the stream and the socket and be ready to receive another task!
Client Side:
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
List<Job> Jobs = (List<Job>)e.Argument;
using (Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
IPEndPoint endpoint = new IPEndPoint(IPAddress.Any, 0);
listener.Bind(endpoint);
listener.Listen(1);
client.ConnectToClient((IPEndPoint)listener.LocalEndPoint);
Socket socket = listener.Accept();
foreach (Job job in Jobs)
{
if (job.IsFile)
{
if (job.IsSend)
{ SendFile(socket, job, e); } //here i send a single file.
// else
// { ReceiveFile(socket, job, e); }
}
// else
// {
// if (job.IsSend)
// { SendDir(socket, job, e); }
// else
// { ReceiveDir(socket, job, e); }
// }
if (worker.CancellationPending)
{
e.Cancel = true;
socket.Dispose();
listener.Dispose();
Console.WriteLine(socket.Connected + " " + listener.Connected);
//it prints "FALSE FALSE"
return;
}
}
}
}
private void SendFile(Socket socket, Job job, DoWorkEventArgs e)
{
UpdateInfo(job.Name, job.Icon); //update GUI with file icon and name.
client.ReceiveFile((_File)job.Argument, bufferSize); //tell the client to start receiving
SendX(socket, ((_File)job.Argument).Path, e); //start sending..
}
private void SendX(Socket socket, string filePath, DoWorkEventArgs e)
{
using (Stream stream = File.OpenRead(filePath))
{
byte[] buffer = new byte[bufferSize];
long sum = 0;
int count = 0;
while (sum < stream.Length)
{
if (worker.CancellationPending)
{
e.Cancel = true;
return;
}
count = stream.Read(buffer, 0, buffer.Length);
socket.Send(buffer, 0, count, SocketFlags.None);
sum += count;
SumAll += count;
worker.ReportProgress((int)((sum * 100) / stream.Length));
}
}
}
Server Side:
public void ConnectToClient(IPEndPoint endpoint)
{
if (client == null)
{
Thread th = new Thread(unused => ConnectTh(endpoint));
th.Start();
}
}
private void ConnectTh(IPEndPoint endpoint)
{
client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
client.Connect(IPAddress.Parse("127.0.0.1"), endpoint.Port);
}
public void ReceiveFile(_File file, int bufferSize)
{
System.Threading.Thread th = new System.Threading.Thread(unused => ReceiveX(client, file.Name, file.Size, bufferSize));
th.Start();
}
private void ReceiveX(Socket client, string destPath, long size, int bufferSize)
{
try
{
using (Stream stream = File.Create(destPath))
{
byte[] buffer = new byte[bufferSize];
long sum = 0;
int count = 0;
while (sum < size)
{
int bytesToReceive = (int)Math.Min(buffer.Length, size - sum);
count = client.Receive(buffer, 0, bytesToReceive, SocketFlags.None);
stream.Write(buffer, 0, count);
sum += count;
}
}
}
catch
{
if (File.Exists(destPath))
File.Delete(destPath);
client.Dispose();
}
}
You should never (have to) count on exceptions for regular program flow.
When the client side shuts down a socket, the server will receive a packet of 0 bytes, and continue to receive that whenever you call Receive. This causes your while loop to last forever. You should handle the situation that count is 0 and treat it as a regular "connection closed by client".
The exception you mentioned only occurs if the client side was unable to shut down properly.