Sockets in Unity - c#

I'm working on a project that requires me to connect to an outside server from my oculus app, I want to do this via pushing a button. I have pretty limited C# knowledge, and would like someone to check my code. I can click the button just fine but initiating the connection doesn't seem to work.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using UnityEngine.UI;
namespace Client
{
}
public class ConnectionCSClient : MonoBehaviour
{
}
public class Click : MonoBehaviour
{
}
class Program
{
public Button ConnectButton;
void Start()
{
Button Button = ConnectButton.GetComponent<Button>();
ConnectButton.onClick.AddListener(TaskOnClick); //Adds a listner on the button
}
void TaskOnClick()
{
if (Input.GetMouseButtonUp(0))
{
Debug.Log("Pressed left click.");
}
if (ConnectButton.onClick = true) try static void ExecuteClient();
{
{
// Establish the remote endpoint
// for the socket. This example
// uses port 11111 on the local
// computer.
IPHostEntry ipHost = Dns.GetHostEntry(Dns.GetHostName());
IPAddress ipAddr = ipHost.AddressList[0];
IPEndPoint localEndPoint = new IPEndPoint(ipAddr, 11111);
// Creation TCP/IP Socket using
// Socket Class Constructor
Socket sender = new Socket(ipAddr.AddressFamily,
SocketType.Stream, ProtocolType.Tcp);
try
{
// 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 message that
// we will send to Server
byte[] messageSent = Encoding.ASCII.GetBytes("Test Client<EOF>");
int byteSent = sender.Send(messageSent);
// Data buffer
byte[] messageReceived = new byte[1024];
// We receive the message 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());
}
}
}

Why do you think you need to work at the level of TCP sockets for this? That would be like opening up and removing the entire dashboard of your car just because the radio isn't working. You don't need to do that. HTTP is built on top of TCP and so HTTP is what you would use for web requests.
Unity provides the WebRequest class specifically for communicating with web servers.

Related

Socket Exception only when connecting over IP but not localhost

System.Net.Sockets.SocketException (0x80004005): A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond
I only get this error when trying to connect via my public IP, if I use localhost it works fine.
My code:
(Note: Public IP/Local IP and Port have been censored here, but I'm using my public IPV4 Address and a specific port which has been Port forwarded as well as allowed through my computers firewall both inbound and outbound)
(Client):
`
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
namespace RemoteBG
{
public partial class Form1 : Form
{
Socket client;
IPEndPoint remote;
public Form1()
{
InitializeComponent();
IPHostEntry host = Dns.GetHostEntry("PUBLICIP");
IPAddress ipAddress = host.AddressList[0];
IPEndPoint remoteEP = new IPEndPoint(ipAddress, PORT);
Socket sender = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
client = sender;
remote = remoteEP;
}
private void TextUpdate(String s)
{
textBox1.AppendText(s + System.Environment.NewLine);
}
private void button1_Click(object sender, EventArgs e)
{
byte[] bytes = new byte[1024];
try
{
// Connect to Remote EndPoint
client.Connect(remote);
Console.WriteLine("Socket connected to {0}",
client.RemoteEndPoint.ToString());
// Encode the data string into a byte array.
byte[] msg = Encoding.ASCII.GetBytes("This is a test<EOF>");
// Send the data through the socket.
int bytesSent = client.Send(msg);
// Receive the response from the remote device.
int bytesRec = client.Receive(bytes);
Console.WriteLine("Echoed test = {0}",
Encoding.ASCII.GetString(bytes, 0, bytesRec));
// Release the socket.
client.Shutdown(SocketShutdown.Both);
client.Close();
}
catch (ArgumentNullException ane)
{
Console.WriteLine("ArgumentNullException : {0}", ane.ToString());
}
catch (SocketException se)
{
TextUpdate("Error connecting to Zang's PC. Error: " + se.ToString());
}
catch (Exception ex)
{
Console.WriteLine("Unexpected exception : {0}", ex.ToString());
}
}
private void button2_Click(object sender, EventArgs e)
{
}
}
}
Server:
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace RemoteBGServer
{
class Program
{
public static int Main(String[] args)
{
StartServer();
return 0;
}
public static void StartServer()
{
IPHostEntry host = Dns.GetHostEntry("LOCALIP");
IPAddress ipAddress = host.AddressList[0];
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, PORT);
try
{
// Create a Socket that will use Tcp protocol
Socket listener = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
// A Socket must be associated with an endpoint using the Bind method
listener.Bind(localEndPoint);
// Specify how many requests a Socket can listen before it gives Server busy response.
// We will listen 10 requests at a time
listener.Listen(10);
Console.WriteLine("Waiting for a connection...");
Socket handler = listener.Accept();
// Incoming data from the client.
string data = null;
byte[] bytes = null;
while (true)
{
bytes = new byte[1024];
int bytesRec = handler.Receive(bytes);
data += Encoding.ASCII.GetString(bytes, 0, bytesRec);
if (data.IndexOf("<EOF>") > -1)
{
break;
}
}
Console.WriteLine("Text received : {0}", data);
byte[] msg = Encoding.ASCII.GetBytes(data);
handler.Send(msg);
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
Console.WriteLine("\n Press any key to continue...");
Console.ReadKey();
}
}
}
`
Expected to see the test message "This is a test" instead got the exception.
This only occurs when using my public ip for IPHostEntry. Localhost works as expected.
Confirmed that the port is forwarded and firewall has exceptions for the port

Why is my server receiving messages on a port it's not listening to? (UDP)

I have a client and server as separate applications for a unity game. This is my first time writing netcode. My code works, but the way I understand it is that it shouldn't be working.
My client is sending messages on port 7052, and listening to messages from the server on port 7062. On the other side, my server is sending messages on 7062, and listening on 7052. On line 54 and 55 of my client code, we can see the client is listening for messages on 7062 via the sendPort integer. But on the server code at line 60 we are sending the messages on 7052, which is the wrong port. The server should not be receiving these messages as it is listening for 7062, but for some reason the message is being received and outputted.
If I set the port to the correct send port, the server does not receive the message. Could someone explain why my code works like this, and if it is correct/incorrect? I want to continue scaling this for more than 1 client, but I would like to know if this solution is correct before I make this bigger. Thank you for any help you can give.
Server code:
using UnityEngine;
using TMPro;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
public class Network : MonoBehaviour
{
TextMeshPro console; //Reference to console in scene
Thread receiveThread; //Thread for listening to messages
UdpClient client; //Reference to client
int recvPort; //Incoming data port
string response;
// Start is called before the first frame update
void Start()
{
//Assign send and receive ports
recvPort = 7052;
//Autoresponse
response = "Server|Message Received";
}
public void Init()
{
//Start Listening
receiveThread = new Thread(new ThreadStart(ReceiveData));
receiveThread.IsBackground = true;
receiveThread.Start();
Debug.Log("Server Started");
}
private void ReceiveData()
{
//Initialize client by accepting data from any IP on the assigned port
client = new UdpClient();
client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
client.Client.Bind(new IPEndPoint(IPAddress.Any, recvPort));
while (true)
{
try
{
//Check for data from any IP on assigned listening port
IPEndPoint anyIP = new IPEndPoint(IPAddress.Any, recvPort);
byte[] data = client.Receive(ref anyIP);
//Convert byte array message to string and output it
string text = Encoding.UTF8.GetString(data);
Debug.Log(text + " Received on port" + anyIP.Port);
//Let the client know the data was received
byte[] resp = Encoding.UTF8.GetBytes(response);
client.Send(resp, resp.Length, anyIP);
}
catch (Exception err)
{
//Output socket error
Debug.Log(err);
}
}
}
}
Client code:
using UnityEngine;
using System.Collections;
using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
public class Client : MonoBehaviour
{
Thread receiveThread; //Thread for listening to messages
IPEndPoint remoteEndPoint; //Remote endpoint for server
UdpClient serverRecv; //udpclient for server??
//Connection info
string IP;
int recvPort;
int sendPort;
// Start is called before the first frame update
void Start()
{
//Assign connection info to server and inbound/outbound ports
IP = "127.0.0.1";
recvPort = 7062;
sendPort = 7052;
remoteEndPoint = new IPEndPoint(IPAddress.Parse(IP), sendPort);
//Bind server to socket and start listening
serverRecv = new UdpClient();
serverRecv.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
serverRecv.Client.Bind(new IPEndPoint(IPAddress.Any, recvPort));
StartListen();
}
//Thread listening for messages
public void StartListen()
{
receiveThread = new Thread(
new ThreadStart(ReceiveData));
receiveThread.IsBackground = true;
receiveThread.Start();
}
private void ReceiveData()
{
while (true)
{
try
{
//Check for data from server on assigned port
IPEndPoint serverIP = new IPEndPoint(IPAddress.Parse(IP), recvPort);
byte[] data = serverRecv.Receive(ref serverIP);
//Convert byte array message to string and output it
string text = Encoding.UTF8.GetString(data);
Debug.Log(text + " Received on port" + serverIP.Port);
}
catch (Exception err)
{
//Output socket error
Debug.Log(err);
}
}
}
public void LogIn()
{
sendString("Client|Hi! I would like to log in");
}
private void sendString(string message)
{
try
{
byte[] data = Encoding.UTF8.GetBytes(message);
serverRecv.Send(data, data.Length, remoteEndPoint);
}
catch (Exception err)
{
Debug.Log(err);
}
}
}
You never set a port that the server sends messages to the client. The server gets the information but the client never recevies anything because the server doesn't send info on the port.

Sockets maintain socket open and just check the messages that the client is sending

What I am trying to do is just check the messages that the client is sending.
what I want is to maintain the socket that was created open and just check the get message that the client send from time to time.
I am using System.Net.Sockets only, I want to make an implementation based on barkeley sockets.
Here is my code,
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Runtime.Remoting.Metadata.W3cXsd2001;
namespace Socket_v1._0
{
class Program
{
private const int BUFSIZE = 200;// Size of receive buffer
private const int BACKLOG = 5; // O valor backlog define o número de pedidos de conexão que podem ser mantidos em espera sem serem aceites pela "system-call" accept.
static void Main(string[] args)
{
int servPort = 8070; //port number
Socket server = null;
try
{
// Create a socket to accept client connections
server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
server.Bind(new IPEndPoint(IPAddress.Any, servPort));
server.Listen(BACKLOG);
}
catch (SocketException se)
{
Console.WriteLine(se.ErrorCode + ": " + se.Message);
Environment.Exit(se.ErrorCode);
}
//for now the server socket is waiting for connections
byte[] rcvBuffer = new byte[BUFSIZE]; // definir buffer
int bytesRcvd = 0 ; // numero de bytes recebidos
for (; ; )
{ // Run forever, accepting and servicing connections
Socket client = null;
try
{
client = server.Accept(); // Get client connection
Console.Write("Handling client at " + client.RemoteEndPoint + " - ");
do {
bytesRcvd = client.Receive(rcvBuffer, 0, rcvBuffer.Length, SocketFlags.None);
string s = Encoding.ASCII.GetString(rcvBuffer, 0, bytesRcvd);
}while (true);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
client.Close();
}
}
}
}
}
So the client send a http get from time to time, i want to see those messages,
for now for the first time this runs the string gets the http get, and because I am maintaining the socket open, I want to wait for the next message (do{}(while(true))).
it goes back to the client.receive, and stops.
after detecting another message from the client it enters in forever loop and the string is empty.
I want something similar to a chat, where the client send messages and the server display the message.
So after opening the socket, what should i do to get the message from the client, then display it , then wait for another message?
One other thing that is bugging me is the client http get:
this is the http get
GET /iclock/cdata?SN=2182682370001&options=all&pushver=2.1.2&language=80 HTTP/1.1
Host: 192.168.1.43:8070
User-Agent: iClock Proxy/1.09
Connection: close
Accept: * / *
What does it mean when it says connection close? do i need create a new socket every time the client want to send a request?
Try to figure it out, i did some changes on the code, inside the do while i have got this
while ((bytesRcvd = client.Receive(rcvBuffer/*, 0, rcvBuffer.Length, SocketFlags.None*/)) > 0)
{
totalBytesEchoed += bytesRcvd;
string s = Encoding.ASCII.GetString(rcvBuffer, 0, bytesRcvd);
Console.WriteLine(s);
}
Image:
so in the image i have got wireshark running and my console app.
according to wireshark the client had tried to send 2 http request, but according to the console it only displayed one...
i want to display the two calls..
a few years ago, i did some exercises about sockets in c language.
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
void main(void)
{
struct sockaddr_in me, from;
int newSock, sock = socket(AF_INET, SOCK_STREAM, 0);
int adl = sizeof(me);
char linha[81];
bzero((char *) &me, adl);
me.sin_family = AF_INET;
me.sin_addr.s_addr = htonl(INADDR_ANY ); /* endereco IP local */
me.sin_port = htons(8450); /* porta local */
if (-1 == bind(sock, (struct sockaddr *) &me, adl))
{
close(sock);
puts("Porta ocupada");
exit(1);
}
listen(sock, 5);
newSock = accept(sock, (struct sockaddr *) &from, &adl);
close(sock);
do
{
read(newSock, linha, 81);
puts(linha);
} while (strcmp(linha, "exit"));
close(newSock);
}
this is in c, so as you can see,after the accept the socket stays open, and the client send the message, it only close the socket when the user send exit to the server...
there may be times where the client doesnt send...but the socket is still open, and when it detects
this is an example of what i want to achive, using the system.net.sockets library,,,
thanks
There are two kinds of sockets: The socket that you use to listen (it is never connected) and the sockets that correspond to connections (each socket represents one connection).
Accept returns you a connected socket to the client that was just accepted. Each call to Accept accepts a new , independent client.
If you want to handle more than one client at a time (which is almost always required) you must ensure that a call to Accept is pending at all times so that new clients can be accepted.
A simple model to achieve this is to accept in a loop forever and start a thread for each client that you accepted:
while (true) {
var clientSocket = listeningSocket.Accept();
Task.Factory.StartNew(() => HandleClient(clientSocket));
}
It might very well be that the client closes the connection.
To detect this on the server side you need to test the result of the call to Receive() against 0.
From MSDN's documentation on Receive() (emphasis by me):
If you are using a connection-oriented Socket, the Receive method will read as much data as is available, up to the number of bytes specified by the size parameter. If the remote host shuts down the Socket connection with the Shutdown method, and all available data has been received, the Receive method will complete immediately and return zero bytes.
From my experience, every time client disconnects from server/listener, this will be registrered on server as SocketException - client has forcibly disconnected. What I do at the moment is just try to catch this and "nicelly" ignore it (log/display some sort of message or run an action to inform the user about this).
Have a look at your code, slightly refactored. Try to run it and see what is happening. I have added some comments to explain a bit. Hope this will help.
There is also class called TcpListenner in .NET you can use to implement behavior you require.
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace SimpleListener
{
class Program
{
const int PORT = 8070;
const int BACKLOG = 5;
static Socket socket;
private static byte[] rcvBuffer;
private static int bytesRcvd;
private static string message;
static void Main(string[] args)
{
try
{
StartListener();
Listen();
}
catch (Exception ex)
{
ShowMessage(ex.Message);
}
}
private static void StartListener()
{
try
{
//Initialize socket and start listenning
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Bind(new IPEndPoint(IPAddress.Any, PORT));
socket.Listen(BACKLOG);
ShowMessage("I'm listenning now..");
}
catch (Exception)
{
throw;
}
}
private static void Listen()
{
try
{
rcvBuffer = new Byte[256];
bytesRcvd = 0;
message = string.Empty;
//Start listnening/waiting for client to connect
while (true)
{
var client = socket.Accept();
ShowMessage("Client with IP " + client.RemoteEndPoint.ToString() + " connected!");
//Client has connected, keep receiving/displaying data
while (true)
{
SocketError rcvErrorCode;
bytesRcvd = 0;
message = string.Empty;
bytesRcvd = client.Receive(rcvBuffer, 0, rcvBuffer.Length, SocketFlags.None);
if (rcvErrorCode != SocketError.Success)
{
Console.WriteLine("Client with IP " + client.RemoteEndPoint.ToString() + " disconnected!");
break;
}
message = Encoding.ASCII.GetString(rcvBuffer, 0, bytesRcvd);
Console.WriteLine(DateTime.Now.ToLongTimeString() + " - " + message);
}
}
}
catch (Exception)
{
throw;
}
}
private static void ShowMessage(string message)
{
Console.WriteLine(message);
Console.WriteLine();
}
}
}

C#. Multicast client-server application

I try to create simple console application 'Chat' using UDP protocol and multicasting. I can only send message from server to client. Server code:
using System;
using System.Text;
using System.Net.Sockets;
using System.Net;
namespace Server
{
class Program
{
static void Main(string[] args)
{
// Create object UdpClient
UdpClient udpClient = new UdpClient();
// IPAddress of group
IPAddress multicastaddress = IPAddress.Parse("224.192.168.255");
try
{
// Join group
udpClient.JoinMulticastGroup(multicastaddress);
}
catch (Exception e)
{
Console.WriteLine("Error: " + e.ToString());
}
// Create object IPEndPoint
IPEndPoint remoteep = new IPEndPoint(multicastaddress, 2345);
// Print message
Console.WriteLine("Server is running ...\n\nEnter message: ");
// Data in Byte []
Byte[] buffer = Encoding.Unicode.GetBytes(Console.ReadLine ());
try
{
// Send data using IPEndPoint
udpClient.Send(buffer, buffer.Length, remoteep);
}
catch (Exception e)
{
Console.WriteLine("Error: " + e.ToString ());
}
// Leave the group
udpClient.DropMulticastGroup(multicastaddress);
// Close connection
udpClient.Close();
}
}
}
Client:
using System;
using System.Text;
using System.Net.Sockets;
using System.Net;
namespace Client
{
class Program
{
static void Main(string[] args)
{
// Create UDP client
UdpClient client = new UdpClient();
// Create new IPEndPoint
IPEndPoint localEp = new IPEndPoint(IPAddress.Any, 2345);
// Set socket options
client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
// Bind to IPEndPoint
client.Client.Bind(localEp);
// IP address
IPAddress multicastaddress = IPAddress.Parse("224.192.168.255");
try
{
// Join group
client.JoinMulticastGroup(multicastaddress);
}
catch (Exception e)
{
Console.WriteLine("Error: " + e.ToString());
}
Console.WriteLine("Client is running ...\n\n");
// Receive data
Byte[] data = client.Receive(ref localEp);
string strData = Encoding.Unicode.GetString(data);
Console.WriteLine("Server: " + strData);
// Leave the group
client.DropMulticastGroup(multicastaddress);
// Close connection
client.Close();
}
}
}
How can I send message from server and receive the response from client, after this send next message and receive response from client etc.? Is it possible to implement this using UdpClient class and multicasting or not?
Thank you very much!

TCP Server to Client

I have made a connection between server and client, the client send data to the server and receive a response, but i wanna send data from the server to client and receive the response from client to server, is it possible ? Here is my code :
[Client] :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace Multi_Client
{
class Program
{
private static Socket _clientSocket = new Socket
(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
static void Main(string[] args)
{
Console.Title = "Client";
ConnectToServer();
RequestLoop();
Exit();
}
private static void ConnectToServer()
{
int attempts = 0;
while (!_clientSocket.Connected)
{
try
{
attempts++;
Console.WriteLine("Connection attempt " + attempts);
_clientSocket.Connect(IPAddress.Loopback, 100);
}
catch (SocketException)
{
Console.Clear();
}
}
Console.Clear();
Console.WriteLine("Connected");
_clientSocket.Send(Encoding.ASCII.GetBytes("C1"));
}
private static void RequestLoop()
{
Console.WriteLine(#"<Type ""exit"" to properly disconnect client>");
SendRequest();
ReceiveResponse();
}
/// <summary>
/// Close socket and exit app
/// </summary>
private static void Exit()
{
SendString("exit"); // Tell the server we re exiting
_clientSocket.Shutdown(SocketShutdown.Both);
_clientSocket.Close();
Environment.Exit(0);
}
private static void SendRequest()
{
Console.Write("Send a request: ");
string request = Console.ReadLine();
SendString(request);
if (request.ToLower() == "exit")
{
Exit();
return;
}
}
private static void SendString(string text)
{
byte[] buffer = Encoding.ASCII.GetBytes(text);
_clientSocket.Send(buffer, 0, buffer.Length, SocketFlags.None);
}
private static void ReceiveResponse()
{
byte[] buffer = new byte[2048];
int received = _clientSocket.Receive(buffer, SocketFlags.None);
if (received == 0) return;
byte[] data = new byte[received];
Array.Copy(buffer, data, received);
string text = Encoding.ASCII.GetString(data);
Console.WriteLine(text);
}
}
}
[Server] :
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Net;
using System.IO;
using NetworkCommsDotNet;
using System.Net.Sockets;
namespace Server
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private static Socket _serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
private static List<Socket> _clientSockets = new List<Socket>();
private static readonly int _BUFFER_SIZE = 2048;
private static byte[] _buffer = new byte[_BUFFER_SIZE];
string text;
Socket current;
Socket test;
delegate void SetTextCallback(string text);
private void SetText(string text)
{
// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if (this.richTextBox1.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetText);
this.Invoke(d, new object[] { text });
}
else
{
this.richTextBox1.Text += text + "\n";
}
}
private void SetupServer()
{
SetText("Setting up server...");
_serverSocket.Bind(new IPEndPoint(IPAddress.Any, 100));
_serverSocket.Listen(5);
_serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), null);
SetText("Server Setup");
}
/// <summary>
/// Close all connected client (we do not need to shutdown the server socket as its connections
/// are already closed with the clients)
/// </summary>
private static void CloseAllSockets()
{
foreach (Socket socket in _clientSockets)
{
socket.Shutdown(SocketShutdown.Both);
socket.Close();
}
_serverSocket.Close();
}
private void AcceptCallback(IAsyncResult AR)
{
Socket socket = null;
try
{
socket = _serverSocket.EndAccept(AR);
}
catch (ObjectDisposedException) // I cannot seem to avoid this (on exit when properly closing sockets)
{
return;
}
_clientSockets.Add(socket);
socket.BeginReceive(_buffer, 0, _BUFFER_SIZE, SocketFlags.None, new AsyncCallback(ReceiveCallback), socket);
SetText("Client connected, waiting for request...");
test = (Socket)AR.AsyncState;
_serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), null);
}
private void ReceiveCallback(IAsyncResult AR)
{
current = (Socket)AR.AsyncState;
int received = 0;
try
{
received = current.EndReceive(AR);
}
catch (SocketException)
{
SetText("Client forcefully disconnected");
current.Close(); // Dont shutdown because the socket may be disposed and its disconnected anyway
_clientSockets.Remove(current);
return;
}
byte[] recBuf = new byte[received];
Array.Copy(_buffer, recBuf, received);
text = Encoding.ASCII.GetString(recBuf);
SetText("Received Text: " + text);
if (text.ToLower() == "get tim") // Client requested time
{
SetText("Text is a get time request");
byte[] data = Encoding.ASCII.GetBytes(DateTime.Now.ToLongTimeString());
current.Send(data);
SetText("Time sent to client");
}
else if (text.ToString() == "C1") // Client wants to exit gracefully
{
SetText("Received :: C1");
byte[] data = Encoding.ASCII.GetBytes(DateTime.Now.ToLongTimeString());
current.Send(data);
}
else
{
SetText("Server is sending invalid packet");
SetText("Warning Sent");
}
current.BeginReceive(_buffer, 0, _BUFFER_SIZE, SocketFlags.None, new AsyncCallback(ReceiveCallback), current);
}
private void Form1_Load(object sender, EventArgs e)
{
SetupServer();
}
private void Send_Received(string mess)
{
byte[] data = Encoding.ASCII.GetBytes(mess);
test.Send(data);
}
private void button2_Click(object sender, EventArgs e)
{
CloseAllSockets();
}
private void button1_Click(object sender, EventArgs e)
{
Send_Received(textBox1.Text);
}
}
}
Short answer: Yes, it is possible.
Long aswer: Yes. Your current code is implemented this way:
Server initializes and prepares to receive connections.
Client tries to connect.
Server accepts connection, adds to clientSockets collection.
Client sends "C1".
Server receives content, interprets, and send answer back.
Client receives answer.
And then you enter a loop, since no other content is sent. You implemented a synchronous protocol - client talks, server talks back, client dumps it to console.
Let me suggest a quick implementation so you can test a server->client->server exchange:
Implement an asynchronous timer on your server.
After 10 seconds, if no incoming message arrives from an specific client, send a "PING?" message to it.
Parse the incoming content on the client. If the message is equal to "PING?", answer with a "PONG!".
This is a very simple QoS protocol - you'll be testing the connection's health.
Let us know if you manage to implement it. =)
Actually, i know where is the problem, when the server send something to the client and the client hasn't already sent something, the client doesn't show the thing until he sent another stuff :O
Example (i know it's complicated) :
Server sent C1 and show in the console C1 sent to client : Client do nothing (he should show in the console C1O)
Client sent Pa (random) and show in the console CAO : Server receive Pa
Client sent Ka (random) and show in the console (Invalid request because the server has received Pa so it sends invalid request text)
I hope that it's clean even if i knew that it's not :S
I resolved it by editing the RequestLoop function :
private static void RequestLoop()
{
ReceiveResponse();
}
It`s all :)

Categories

Resources