I am writing program to solve the dining philosophers problem without a server. It should work by message passing. My application should run 5 times and then connect to each other and solve the problem by themselves. I put a server side and client side in each app, and I gave them a port number. This image will show what i am talking about:
https://www.photobox.co.uk/my/photo/full?photo_id=500223105218
All I want is sending messages between client sides and server sides.
But I have an error in sending message asynchronously from server side by socket handler.(mentioned it below)
I searched about that but could not find any code similar, so how can I send messages directly from server side to client side?
And, how is my idea? is that right? or it is wrong.
This is part of my code which works well:
String status = "Thinking";
Boolean right = false;
Boolean left = false;
// Receiving byte array
byte[] bytes = new byte[1024];
SocketPermission permission;
Socket sListener;
Socket sListener1;
Socket sListener2;
Socket sListener3;
Socket sListener4;
Socket handler1;
Socket handler2;
Socket handler3;
Socket handler4;
Socket handler5;
Socket senderSock;
Socket senderSock1;
Socket senderSock2;
Socket senderSock3;
Socket senderSock4;
public Form1()
{
InitializeComponent();
}
//start button
private void button1_Click(object sender, EventArgs e)
{
try
{
IPEndPoint ipEndPoint=null;
IPEndPoint ipEndPoint1=null;
IPEndPoint ipEndPoint2 = null;
IPEndPoint ipEndPoint3 = null;
IPEndPoint ipEndPoint4 = null;
// Creates one SocketPermission object for access restrictions
permission = new SocketPermission(
NetworkAccess.Accept, // Allowed to accept connections
TransportType.Tcp, // Defines transport types
"", // The IP addresses of local host
SocketPermission.AllPorts // Specifies all ports
);
// Listening Socket object
sListener = null;
sListener1 = null;
sListener2 = null;
sListener3 = null;
sListener4 = null;
// Ensures the code to have permission to access a Socket
permission.Demand();
// Resolves a host name to an IPHostEntry instance
IPHostEntry ipHost = Dns.GetHostEntry("");
// Gets first IP address associated with a localhost
IPAddress ipAddr = ipHost.AddressList[0];
// Creates a network endpoint
if (Sport.Text == "1000")
{
ipEndPoint = new IPEndPoint(ipAddr, Convert.ToInt32(Sport.Text));
}else if (Sport.Text == "1001")
{
ipEndPoint1 = new IPEndPoint(ipAddr, Convert.ToInt32(Sport.Text));
}
else if (Sport.Text == "1002")
{
ipEndPoint2 = new IPEndPoint(ipAddr, Convert.ToInt32(Sport.Text));
}
else if (Sport.Text == "1003")
{
ipEndPoint3 = new IPEndPoint(ipAddr, Convert.ToInt32(Sport.Text));
}
else if (Sport.Text == "1004")
{
ipEndPoint4 = new IPEndPoint(ipAddr, Convert.ToInt32(Sport.Text));
}
// Associates a Socket with a local endpoint
if (Sport.Text == "1000")
{
// Create one Socket object to listen the incoming connection
sListener = new Socket(
ipAddr.AddressFamily,
SocketType.Stream,
ProtocolType.Tcp
);
sListener.Bind(ipEndPoint);
sListener.Listen(10);
}else if(Sport.Text == "1001")
{
sListener1 = new Socket(
ipAddr.AddressFamily,
SocketType.Stream,
ProtocolType.Tcp
);
sListener1.Bind(ipEndPoint1);
sListener1.Listen(10);
}
else if (Sport.Text == "1002")
{
sListener2 = new Socket(
ipAddr.AddressFamily,
SocketType.Stream,
ProtocolType.Tcp
);
sListener2.Bind(ipEndPoint2);
sListener2.Listen(10);
}
else if (Sport.Text == "1003")
{
sListener3 = new Socket(
ipAddr.AddressFamily,
SocketType.Stream,
ProtocolType.Tcp
);
sListener3.Bind(ipEndPoint3);
sListener3.Listen(10);
}
else if (Sport.Text == "1004")
{
sListener4 = new Socket(
ipAddr.AddressFamily,
SocketType.Stream,
ProtocolType.Tcp
);
sListener4.Bind(ipEndPoint4);
sListener4.Listen(10);
}
label3.Text = "Server started.";
statusLabel.Text = "READY";
button1.Enabled = false;
}
catch (Exception exc) { MessageBox.Show(exc.ToString()); }
}
//connect button
private void button2_Click(object sender, EventArgs e)
{
try
{
IPEndPoint ipEndPoint = null;
IPEndPoint ipEndPoint1 = null;
IPEndPoint ipEndPoint2 = null;
IPEndPoint ipEndPoint3 = null;
IPEndPoint ipEndPoint4 = null;
// Create one SocketPermission for socket access restrictions
SocketPermission permission = new SocketPermission(
NetworkAccess.Connect, // Connection permission
TransportType.Tcp, // Defines transport types
"", // Gets the IP addresses
SocketPermission.AllPorts // All ports
);
// Ensures the code to have permission to access a Socket
permission.Demand();
// Resolves a host name to an IPHostEntry instance
IPHostEntry ipHost = Dns.GetHostEntry("");
// Gets first IP address associated with a localhost
IPAddress ipAddr = ipHost.AddressList[0];
// Creates a network endpoint
if (Cport.Text == "1000")
{
ipEndPoint = new IPEndPoint(ipAddr, Convert.ToInt32(Cport.Text));
}else if (Cport.Text == "1001")
{
ipEndPoint1 = new IPEndPoint(ipAddr, Convert.ToInt32(Cport.Text));
}
else if (Cport.Text == "1002")
{
ipEndPoint2 = new IPEndPoint(ipAddr, Convert.ToInt32(Cport.Text));
}
else if (Cport.Text == "1003")
{
ipEndPoint3 = new IPEndPoint(ipAddr, Convert.ToInt32(Cport.Text));
}
else if (Cport.Text == "1004")
{
ipEndPoint4 = new IPEndPoint(ipAddr, Convert.ToInt32(Cport.Text));
}
if (Cport.Text == "1000")//A
{
// Create one Socket object to setup Tcp connection
senderSock = new Socket(
ipAddr.AddressFamily,// Specifies the addressing scheme
SocketType.Stream, // The type of socket
ProtocolType.Tcp // Specifies the protocols
);
senderSock.NoDelay = false; // Using the Nagle algorithm
// Establishes a connection to a remote host
senderSock.Connect(ipEndPoint);
statusLabel.Text = "Socket connected to " + senderSock.RemoteEndPoint.ToString();
}
else if (Cport.Text == "1001")//B
{
senderSock1 = new Socket(
ipAddr.AddressFamily,
SocketType.Stream,
ProtocolType.Tcp
);
senderSock1.NoDelay = false;
senderSock1.Connect(ipEndPoint1);
statusLabel.Text = "Socket connected to " + senderSock1.RemoteEndPoint.ToString();
}
else if (Cport.Text == "1002")//C
{
senderSock2 = new Socket(
ipAddr.AddressFamily,
SocketType.Stream,
ProtocolType.Tcp
);
senderSock2.NoDelay = false;
senderSock2.Connect(ipEndPoint2);
statusLabel.Text = "Socket connected to " + senderSock2.RemoteEndPoint.ToString();
}
else if (Cport.Text == "1003")//D
{
senderSock3 = new Socket(
ipAddr.AddressFamily,
SocketType.Stream,
ProtocolType.Tcp
);
senderSock3.NoDelay = false;
senderSock3.Connect(ipEndPoint3);
statusLabel.Text = "Socket connected to " + senderSock3.RemoteEndPoint.ToString();
}
else if (Cport.Text == "1004")//E
{
senderSock4 = new Socket(
ipAddr.AddressFamily,
SocketType.Stream,
ProtocolType.Tcp
);
senderSock4.NoDelay = false;
senderSock4.Connect(ipEndPoint4);
statusLabel.Text = "Socket connected to " + senderSock4.RemoteEndPoint.ToString();
}
button2.Enabled = false;
}
catch (Exception exc) { MessageBox.Show(exc.ToString()); }
label3.Text = "wait...";
Thread.Sleep(4000);
send_st();
}
And here is my code where I get an Error in "Send(handler1, status);"
The error is: "Object reference not set to an instance of an object"
//send status from clnt to server
public void sendCToS(String str)
{
try
{
// Sending message
//<Client Quit> is the sign for end of data
byte[] msg = Encoding.Unicode.GetBytes(str + "<Client Quit>");
// Sends data to a connected Socket.
//send status from client to server
int bytesSend = senderSock.Send(msg);//receiver server tasmim giri va response send mikone
}
catch (Exception exc) { MessageBox.Show(exc.ToString()); }
}
//it send hungry status from both to both!
public void send_st()
{
// Resolves a host name to an IPHostEntry instance
IPHostEntry ipHost = Dns.GetHostEntry("");
// Gets first IP address associated with a localhost
IPAddress ipAddr = ipHost.AddressList[0];
Random rnd = new Random();
int delay = rnd.Next(2000, 5000);
while (true)
{
//System.Threading.Thread.Sleep(2000);
statusLabel.Text = status;
statusLabel.ForeColor = System.Drawing.Color.Blue;
Thread.Sleep(delay);
if (Sport.Text == "1000")//A
{
status = "hungry";
statusLabel.Text = "HUNGRY";
statusLabel.ForeColor = System.Drawing.Color.Red;
//send status from server to clint
Send(handler1, status);
//send status from clnt to server
sendCToS(status);
label3.Text = "status Sent to left and right";
}
else if (Sport.Text == "1001")//B
{
Thread.Sleep(2000);
status = "hungry";
statusLabel.Text = "HUNGRY";
statusLabel.ForeColor = System.Drawing.Color.Red;
//send status from server to clint
Send(handler2, status);
//send status from clnt to server
sendCToS(status);
label3.Text = "status Sent to left and right";
}
else if (Sport.Text == "1002")//C
{
status = "hungry";
statusLabel.Text = "HUNGRY";
statusLabel.ForeColor = System.Drawing.Color.Red;
//send status from server to clint
Send(handler3, status);
//send status from clnt to server
sendCToS(status);
label3.Text = "status Sent to left and right";
}
else if (Sport.Text == "1003")//D
{
Thread.Sleep(2000);
status = "hungry";
statusLabel.Text = "HUNGRY";
statusLabel.ForeColor = System.Drawing.Color.Red;
//send status from server to clint
Send(handler4, status);
//send status from clnt to server
sendCToS(status);
label3.Text = "status Sent to left and right";
}
else if (Sport.Text == "1004")//E
{
Thread.Sleep(3000);
status = "hungry";
statusLabel.Text = "HUNGRY";
statusLabel.ForeColor = System.Drawing.Color.Red;
//send status from server to clint
Send(handler5, status);
//send status from clnt to server
sendCToS(status);
label3.Text = "status Sent to left and right";
}
}
}
//server side
// Thread signal.
public static ManualResetEvent allDone = new ManualResetEvent(false);
public void AcceptCallback(IAsyncResult ar)
{
Socket listener = null;
// A new Socket to handle remote host communication
Socket handler = null;
try
{
// Receiving byte array
byte[] buffer = new byte[1024];
// Get Listening Socket object
listener = (Socket)ar.AsyncState;
// Create a new socket
handler = listener.EndAccept(ar);
// Using the Nagle algorithm
handler.NoDelay = false;
StateObject state = new StateObject();
// Begins to asynchronously receive data
handler.BeginReceive(
buffer, // An array of type Byt for received data
0, // The zero-based position in the buffer
buffer.Length, // The number of bytes to receive
0,// Specifies send and receive behaviors
new AsyncCallback(ReceiveCallback),//An AsyncCallback delegate
state // Specifies infomation for receive operation
);
}
catch (Exception exc) { MessageBox.Show(exc.ToString()); }
}
public void ReceiveCallback(IAsyncResult ar)
{
String response = "ok";
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);
// Received message
string content = string.Empty;
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.
content = state.sb.ToString();
if (content.IndexOf("<Client Quit>") > -1)
{
// All the data has been read from the client
label3.Text = content;
}
else {
// Not all data received. Get more.
handler.BeginReceive(state.buffer, 0,StateObject.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state);
}
And this is the rest of the server side functions:
//func for echo back to client
private 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);
}
public void SendCallback(IAsyncResult ar)
{
try
{
// A Socket which has sent the data to remote host
Socket handler = (Socket)ar.AsyncState;
// The number of bytes sent to the Socket
int bytesSend = handler.EndSend(ar);
label3.Text = "Sent {0} bytes to Client" + bytesSend;
}
catch (Exception exc) { MessageBox.Show(exc.ToString()); }
I belive the problem is with this line:
senderSock.Send(msg);
You never instantiated the senderSock, you only declared it.
try this:
senderSock= new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
senderSock.Send(msg);
Related
so for my UDP C# chat application, I have a server program which is intended to recieve a response by listening for the client to send it on Port 8001, when it recieves the acknolwedement from the client it is supposed to send a message back to the client. However, though the client and server both say they are listening for each other, the server always immediately reports that it sent the message to IP address 0.0.0.0, so they are not linking, below is the code to the client and server:
Server:
const int listenPort = 8001;
bool done = false;
UdpClient listener = new UdpClient(listenPort);
try
{
while (!done)
{
string text_to_send = satt.Text;
if (text_to_send.Length == 0)
{
done = true;
}
else
{
byte[] send_buffer = Encoding.ASCII.GetBytes(text_to_send);
try
{
string IPAddress1 = "";
IPHostEntry Host = default(IPHostEntry);
string Hostname = null;
Hostname = System.Environment.MachineName;
Host = Dns.GetHostEntry(Hostname);
foreach (IPAddress IP in Host.AddressList)
{
if (IP.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
{
IPAddress1 = Convert.ToString(IP);
}
else
{
IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, listenPort);
string data_recieved;
byte[] recieve_byte_array;
try
{
while (!done)
{
Console.WriteLine("Looking for attack buddies " + groupEP);
recieve_byte_array = listener.Receive(ref groupEP);
Console.WriteLine("New buddy found at + " + groupEP.ToString());
data_recieved = Encoding.ASCII.GetString(recieve_byte_array, 0, recieve_byte_array.Length);
Console.WriteLine(data_recieved);
}
}
catch (Exception n)
{
Console.WriteLine("Attack information could not be sent. Please make sure your buddies are reachable" + n.ToString());
}
}
}
}
catch (Exception j)
{
Console.WriteLine("Please make sure all needed information is filled out");
}
Client:
const int listenPort = 8001;
bool done = false;
UdpClient listener = new UdpClient(listenPort);
IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, listenPort);
string data_recieved;
string searchcount_sent = searchcount.ToString();
byte[] send_byte_array;
byte[] recieve_byte_array;
try
{
while (!done)
{
string IPAddress1 = "";
IPHostEntry Host = default(IPHostEntry);
string Hostname = null;
Hostname = System.Environment.MachineName;
Host = Dns.GetHostEntry(Hostname);
foreach (IPAddress IP in Host.AddressList)
{
if (IP.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
{
IPAddress1 = Convert.ToString(IP);
}
}
string text_to_send = "Request to connect from: " + IPAddress1;
if (text_to_send.Length == 0)
{
done = true;
}
else
{
MessageBox.Show("Now listening on port 8001.");
Socket sending_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
IPAddress send_to_address = IPAddress.Parse(RecieveIP.Text);
IPEndPoint sending_end_point = new IPEndPoint(send_to_address, 8001);
Console.WriteLine("Now sending out packet to be acknolwedged by lead computer.");
byte[] send_buffer = Encoding.ASCII.GetBytes(text_to_send);
Console.WriteLine("Listening for the attack information on port " + listenPort);
recieve_byte_array = listener.Receive(ref groupEP);
data_recieved = Encoding.ASCII.GetString(recieve_byte_array, 0, recieve_byte_array.Length);
try
{
sending_socket.SendTo(send_buffer, sending_end_point);
}
catch (Exception send_exception)
{
Console.WriteLine("Exception {0}", send_exception);
}
MessageBox.Show("Listening for attack information.");
The two computers are finding each other via arp-a. So wondering why they would not be receiving each others message? Thanks.
i've been tasked with writing a multi-threaded client (has a thread for sending data and a different thread for receiving data). for some reason the client (the one who pays for my job) insists that I use the same port for both sending (to the server) and receiving data (from the server). from what I remember this shouldn't be possible so that's why I'm here, to see if I was wrong.
sending thread:
public void Send_msg()
{
while (!GlobalVar.is_conn) { }
try
{
socket = new Socket(AddressFamily.InterNetwork, GlobalVar._isTcp ? SocketType.Stream : SocketType.Dgram, GlobalVar._isTcp ? ProtocolType.Tcp : ProtocolType.Udp);
IPEndPoint end_point = new IPEndPoint(Mul_ip, Mul_port);
if (GlobalVar._isTcp)
{
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseUnicastPort, true);
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, true);
}
else
{
socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(Mul_ip, IPAddress.Any));
}
socket.Bind(new IPEndPoint(IPAddress.Any,Mul_port));
socket.Connect(end_point);
GlobalVar.socketWasConfiged = true;
while (!_shouldStop)
{
while (!Send_msg_queue.IsEmpty)
{ //while there are more messages to send
Send_msg_queue.TryDequeue(out CM_msg send_msg);
byte[] send_buff = Encoder(send_msg);
try
{
socket.Send(send_buff, SocketFlags.None);
GlobalVar.Is_Wd_Rec = false;
}
catch (Exception e)
{
MessageBox.Show("Error while trying to send a message: " + e.Message, "Error");
}
}
}
}
catch(Exception e)
{
MessageBox.Show("Error while trying to send a message: " + e.Message, "Error");
}
finally
{
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, true);
socket.Close();
}
as can be seen I open a socket, change its options via the setSocketOption, then I bind and connect to the server, afterwards the thread samples some queue and sends messages when there are so be sent.
simultaneously the thread that is supposed to be receiving messages does this:
public void Receive_msg()
{
while (!GlobalVar.is_conn) { }
try
{
while (!GlobalVar.socketWasConfiged) { }
byte[] rec_buff = new byte[size];
socket = new Socket(AddressFamily.InterNetwork,GlobalVar._isTcp? SocketType.Stream : SocketType.Dgram,GlobalVar._isTcp? ProtocolType.Tcp : ProtocolType.Udp);
IPEndPoint end_point = new IPEndPoint(IPAddress.Any, Mul_port);
if(GlobalVar._isTcp)
{
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseUnicastPort, true);
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1);
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, true);
}
else
{
socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(Mul_ip, IPAddress.Any));
}
socket.Bind(end_point);
socket.Connect(new IPEndPoint(Mul_ip, Mul_port));
while (!_shouldStop)
{
size_rec = socket.Receive(rec_buff);
GlobalVar.Counter_auto = GlobalVar.Counter_auto + 1;
Receive_msg_queue.Enqueue(Decoder(rec_buff));
// if a message was recieved than there is a connection to the unit, so we make Is_Wd_Rec true
GlobalVar.Is_Wd_Rec = true;
}
}
catch (Exception e)
{
MessageBox.Show("An error occur while trying to receive a message: " + e.Message);
}
finally
{
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, true);
socket.Close();
}
}
as can be seen, the listener thread waits till some globalVar is true (so we don't get concurrent socket binds), and then it initializes the socket and tries to bind/connect to the server. once it tries to connect I get an exception that it cannot connect to a socket that is already connected.
is there any way to work around this? or should I be telling the client that the server should write to a different port?
I have a small server that is received and sends the message back to the client.
this is the client-side
when I open the client it will connect to server through Connect()
public Form1()
{
InitializeComponent();
Connect();
CheckForIllegalCrossThreadCalls = false;
}
this is my connect
void Connect()
{
ipep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 9999);
server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
server.Connect(ipep);
}
catch (SocketException e)
{
MessageBox.Show(Convert.ToString(e));
}
Thread listen = new Thread(Receive);
listen.IsBackground = true; ;
listen.Start();
}
and I have a receive like this
void Receive()
{
datarec = new byte[1024];
try
{
while (true)
{
string StringData;
rec = server.Receive(datarec);
StringData = Encoding.ASCII.GetString(data, 0, rec);
txtShow.Text = StringData;
}
}
catch
{
Close();
}
}
and I send data through a button have Send method
void Send(string s)
{
data = new byte[1024];
data = Encoding.ASCII.GetBytes(s);
server.Send(data, data.Length, SocketFlags.None);
}
Send button
private void button1_Click(object sender, EventArgs e)
{
string s = txtText.Text;
Send(s);
}
this is the server-side
I have a thread server
public static void Process(Socket client)
{
byte[] data = new byte[1024];
int recv;
string dataInput;
IPEndPoint clientep = (IPEndPoint)client.RemoteEndPoint;
Console.WriteLine("Connected with {0} at port {1}", clientep.Address, clientep.Port);
while (true)
{
try
{
recv = client.Receive(data);
dataInput = Encoding.ASCII.GetString(data, 0, recv);
Console.WriteLine(dataInput);
client.Send(data);
}
catch (SocketException e)
{
Console.WriteLine(e);
}
}
}
this is the server main
public static void Main()
{
byte[] rec = new byte[1024];
IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 9999);
Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
server.Bind(ipep);
server.Listen(10);
Console.WriteLine("Waiting for client...");
Console.WriteLine("LOG CHAT");
while (true)
{
Socket client = server.Accept();
Core core = new Core();
Thread t = new Thread(() => Core.Process(client));
t.Start();
}
}
the server receive message but when it sends a message back it has an error "An established connection was aborted by the software in your host machine"
Can you guys tell me where I was wrong and how can I fix it?
When you call client.Send(data) in your server code, you will send the whole 1024 byte buffer back to the client, not just the data received.
Encoding.ASCII.GetString in the client could fail when processing this garbage and the exception will close the connection.
Try to replace client.Send(data) by client.Send(data, recv, SocketFlags.None).
Also, you should not update UI controls directly from a background thread, Use Control.Invoke for this. Failing to do so will also throw an exception and close the connection.
I have a console application which acts as a socket server. It should accept data 24/7 from a number of clients, but issue is that the clients cannot establish connection after sometime (not constant). after closing & opening the connection works & it continues to next point of time.
Server
public static void ExecuteServer()
{
int portNumber = 11111;
string _responseMessageToClient = "";
IPHostEntry ipHost = Dns.GetHostEntry(Dns.GetHostName());
IPAddress ipAddr = ipHost.AddressList[0];
IPEndPoint localEndPoint = new IPEndPoint(ipAddr, portNumber);
// Creation TCP/IP Socket using
// Socket Class Costructor
Socket listener = new Socket(ipAddr.AddressFamily,
SocketType.Stream, ProtocolType.Tcp);
bool doBroadCast = false;
try
{
listener.Bind(localEndPoint);
listener.Listen(10);
while (true)
{
try`enter code here`
{
Socket clientSocket = listener.Accept();
// Data buffer
byte[] bytes = new Byte[1024*2];//2048
string data = null;
while (true)
{
try
{
if (clientSocket.Connected)
{
int numByte = clientSocket.Receive(bytes);
data += Encoding.ASCII.GetString(bytes,
0, numByte);
if (data.IndexOf("!") > -1)
break;
}
else
{
Console.WriteLine("Disconnected {0}", clientSocket.LocalEndPoint);
break;
}
}
catch (Exception e)
{
//ErrorLogProvider.Save(e);
Console.WriteLine(e.ToString());
break;
}
}
Console.WriteLine("Text received -> {0} ", data);
if (clientSocket.Connected)
{
clientSocket.Send(message);
}
clientSocket.Shutdown(SocketShutdown.Both);
clientSocket.Close();
}
catch (Exception e)
{
}
}
}
catch (Exception e)
{
}
}
This server has to be running continuously - Client code given below
static void ExecuteClient()
{
try
{
// Establish the remote endpoint
// for the socket. This example
// uses port 11111 on the local
// computer.
int portNumber = 11111;
IPHostEntry ipHost = Dns.GetHostEntry(Dns.GetHostName());
IPAddress ipAddr = ipHost.AddressList[0];
IPEndPoint localEndPoint = new IPEndPoint(ipAddr, portNumber);
// Creation TCP/IP Socket using
// Socket Class Costructor
Socket sender = new Socket(ipAddr.AddressFamily,
SocketType.Stream, ProtocolType.Tcp);
long i = 0;
try
{
//while (i < 10)
//{
// Connect Socket to the remote
// endpoint using method Connect()
sender.Connect(localEndPoint);
// We print EndPoint information
// that we are connected
Console.WriteLine("Socket connected to -> {0} ",
sender.RemoteEndPoint.ToString());
// Creation of messagge that
// we will send to Server
byte[] messageSent = Encoding.ASCII.GetBytes("^check!");
int byteSent = sender.Send(messageSent);
// Data buffer
byte[] messageReceived = new byte[1024];
// We receive the messagge using
// the method Receive(). This
// method returns number of bytes
// received, that we'll use to
// convert them to string
int byteRecv = sender.Receive(messageReceived);
Console.WriteLine("Message from Server -> {0}",
Encoding.ASCII.GetString(messageReceived,
0, byteRecv));
//}
// Close Socket using
// the method Close()
sender.Shutdown(SocketShutdown.Both);
sender.Close();
}
// Manage of Socket's Exceptions
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());
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
I've got this code somewhere from SO if I remember that correctly.
LoopClients just checks for new clients and handles them by spawning a new thread.
class Server {
private TcpListener _server;
private Boolean _isRunning = true;
private int m_Port = 12001;
private Thread m_ServerThread;
public Server (int p_Port) {
_server = new TcpListener(IPAddress.Any, m_Port);
_server.Start( );
m_ServerThread = new Thread(new ThreadStart(LoopClients));
m_ServerThread.Start( );
}
public void ShutdownServer() {
_isRunning = false;
}
public void LoopClients ( ) {
while ( _isRunning ) {
// wait for client connection
TcpClient newClient = _server.AcceptTcpClient( );
// client found.
// create a thread to handle communication
Thread t = new Thread(new ParameterizedThreadStart(HandleClient));
t.Start(newClient);
}
}
public void HandleClient (object obj) {
try {
// retrieve client from parameter passed to thread
TcpClient client = (TcpClient) obj;
// sets two streams
StreamWriter sWriter = new StreamWriter(client.GetStream( ), Encoding.ASCII);
StreamReader sReader = new StreamReader(client.GetStream( ), Encoding.ASCII);
// you could use the NetworkStream to read and write,
// but there is no forcing flush, even when requested
String sData = null;
while ( client.Connected ) {
sData = sReader.ReadToEnd( );
if ( sData != "" )
break;
}
try {
sWriter.WriteLine("test");
} catch(Exception ex) {
Console.WriteLine(ex.Message);
}
sWriter.Dispose( );
sReader.Dispose( );
sWriter = null;
sReader = null;
} catch ( IOException ioe ) {
}
}
}
Client is somewhat shorter. I've got to shorten the code a bit here.
Client:
private void sendDataViaTCP () {
TcpClient l_Client = new TcpClient();
l_Client.Connect(IP, Port);
Stream l_Stream = l_Client.GetStream( );
StreamWriter l_SW = new StreamWriter(l_Stream);
StreamReader l_SR = new StreamReader(l_SW.BaseStream);
try {
l_SW.WriteLine(Msg);
l_SW.Flush( );
String l_IncomingData;
while ( ( l_IncomingData = l_SR.ReadToEnd()) != "") {
AddLineToLog(l_IncomingData);
}
} finally {
l_SW.Close( );
}
}
I have a basic C#.NET UDP server and client code and I am trying to port it to UWP. For UWP, I experimented with DatagramSocket and regular Socket class. I am seeing almost 40% packet drops on incoming UDP packets on UWP Server using DatagramSocket class. If I use UWP Sockets, I see the packet loss of around 70%. The old .NET code shows 0% packet loss.
I am thinking maybe I am not using the UWP APIs correctly and hence I am getting poor performance. Could someone guide me on how to improve UWP server performance?
Right now, all the tests are done using loop-back. UWP doesn't allow loop-back by default so I am followed the instructions mentioned here to enable loop-back.
The server listens for packet on 50000 port and Client code sends packets of around 60 bytes to server from 50001.
The C#.NET client code is below:
try
{
byte[] buffer = new byte[1024];
IPEndPoint localEP = new IPEndPoint(IPAddress.Any, 50001);
IPAddress remoteIp = System.Net.IPAddress.Parse("127.0.0.1");
IPEndPoint remoteEP = new IPEndPoint(remoteIp, 50000);
Socket sender = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
try
{
sender.Bind(localEP);
for(int i = 0; i < 10000; i++)
{
//Thread.Sleep(1);
// Encode the data string into a byte array.
string ClientReq = "Client Request:: " + i.ToString() + " "+ Guid.NewGuid().ToString();
byte[] msg = Encoding.ASCII.GetBytes(ClientReq);
// Send the data through the socket.
int sentBytes = sender.SendTo(msg, remoteEP);
Console.WriteLine("{0}::{1} Client Request ({2} bytes):: {3}.",
remoteEP.Address.ToString(),
remoteEP.Port.ToString(),
sentBytes,
ClientReq
);
}
// Release the socket.
sender.Close();
//Console.ReadKey();
}
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());
}
}
catch(Exception e)
{
Console.WriteLine(e.ToString());
}
C#.NET Server Code:
byte[] buffer = new Byte[1024];
IPAddress LocalIp = IPAddress.Any; //System.Net.IPAddress.Parse("127.0.0.1");
IPEndPoint localEndPoint = new IPEndPoint(LocalIp, 50000);
// Create a UDP/IP socket.
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp );
// Bind the socket to the local endpoint and
// listen for incoming connections.
try
{
listener.Bind(localEndPoint);
Console.WriteLine("Bind Complete");
int messagesReceived = 0;
while(true)
{
EndPoint receiveEP = new IPEndPoint(IPAddress.Any, 0);
int receivedBytes = listener.ReceiveFrom(buffer, ref receiveEP);
messagesReceived++;
IPEndPoint receiveIPEP = receiveEP as IPEndPoint;
Console.WriteLine("{0}::{1}::{2} Client Request ({3} bytes):: {4}.",
messagesReceived,
receiveIPEP.Address.ToString(),
receiveIPEP.Port.ToString(),
receivedBytes,
System.Text.Encoding.UTF8.GetString(buffer, 0, receivedBytes));
}
}
catch(Exception e)
{
Console.WriteLine(e.ToString());
}
With this above code, i see all the 10000 packets are received at server.
UWP DatagramSocket Code:
DgSocket = new DatagramSocket();
DgSocket.MessageReceived += SocketListener_MessageReceived;
await DgSocket.BindServiceNameAsync("50000");
private async void SocketListener_MessageReceived(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args)
{
uint datalen = args.GetDataReader().UnconsumedBufferLength;
DataReader reader = args.GetDataReader();
byte[] dataBuffer = new byte[reader.UnconsumedBufferLength];
reader.ReadBytes(dataBuffer);
await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
lock(_lockObject)
{
DgPackets++;
DgPacketList.Add(Encoding.ASCII.GetString(dataBuffer));
}
});
}
UWP Socket Code:
public void SetupSimpleSocketListener()
{
try
{
IPAddress LocalIp = IPAddress.Any;
IPEndPoint localEndPoint = new IPEndPoint(LocalIp, 50000);
SimpleSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp );
byte[] buffer = new Byte[1024];
SimpleSocket.Bind(localEndPoint);
Debug.WriteLine("Bind Complete");
SocketAsyncEventArgs sockarg = new SocketAsyncEventArgs();
sockarg.Completed += Sockarg_Completed;
sockarg.RemoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
sockarg.SetBuffer(buffer, 0, buffer.Length);
if(!SimpleSocket.ReceiveFromAsync(sockarg))
{
Sockarg_Completed(this, sockarg);
}
}
catch(Exception e)
{
Debug.WriteLine(e.ToString());
}
}
private async void Sockarg_Completed(object sender, SocketAsyncEventArgs e)
{
await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
lock(_lockObject)
{
SimpleSocketPackets++;
SimpleSocketPacketList.Add(Encoding.ASCII.GetString(e.Buffer, 0, e.BytesTransferred));
}
});
if(e.SocketError == System.Net.Sockets.SocketError.Success)
{
if(!SimpleSocket.ReceiveFromAsync(e))
{
Sockarg_Completed(this, e);
}
}
}
I have posted the full source code on github: