I am starting on Android and in my first application I need to establish a communication between and android table a PC. The communication is direct by staqtic IPs as I need that when I have several PCs and tablets each table only communicates with its PC.
The communication from the tablet to the Pc is already working but from the PC to the table I cannot get data transfered
Android side
public class Server implements Runnable
{
#Override
public void run()
{
while (always==true)
{
while(start2==false)
{
}
try
{
InetAddress serverAddr = InetAddress.getByName("192.168.173.133");
updatetrack("\nServer: Start connecting\n");
//*DatagramSocket socket = new DatagramSocket(SERVERPORT2, serverAddr);/
DatagramSocket socket = new DatagramSocket(SERVERPORT2);
byte[] buf = new byte[17];
DatagramPacket packet = new DatagramPacket(buf, buf.length, serverAddr, SERVERPORT2);
//*DatagramPacket packet = new DatagramPacket(buf, buf.length);/
updatetrack("Server: Receiving\n");
socket.receive(packet);
updatetrack("Server: Message received: '" + new String(packet.getData()) + "'\n");
updatetrack("Server: Succeed!\n");
start2=false;
}
catch (Exception e)
{
updatetrack("Server: Error!\n");
start2=false;
}
}
}
}
192.168.173.133 is the table IP and SERVERPORT2 is 4445
When I start the application it remains waiting for data after displaying "Server: Receiving" but
C# code
public static void Main()
{
IPEndPoint iep2 = new IPEndPoint(IPAddress.Parse("192.168.173.133"), 4445);
string hostname = Dns.GetHostName();
byte[] data = Encoding.ASCII.GetBytes(hostname);
sock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);
sock.SendTo(data, iep2);
sock.Close();
}
I suppose that it is any silly think I am forgotten but after reading many forums and books I am stopped on this point
Any advise will be welcome
You use UDP connection and socket.receive(packet) doesn't wait for packet. If there isn't packet in the buffer this operation throw exception.
Try to change your code to:
#Override
public void run()
{
while (always==true)
{
while(start2==false)
{
}
try
{
InetAddress serverAddr = InetAddress.getByName("192.168.173.133");
updatetrack("\nServer: Start connecting\n");
//*DatagramSocket socket = new DatagramSocket(SERVERPORT2, serverAddr);/
DatagramSocket socket = new DatagramSocket(SERVERPORT2);
while (always==true)
{
try{
byte[] buf = new byte[17];
DatagramPacket packet = new DatagramPacket(buf, buf.length, serverAddr, SERVERPORT2);
//*DatagramPacket packet = new DatagramPacket(buf, buf.length);/
updatetrack("Server: Receiving\n");
socket.receive(packet);
updatetrack("Server: Message received: '" + new String(packet.getData()) + "'\n");
updatetrack("Server: Succeed!\n");
start2=false;
}
catch(Exception ex) {ex.printStackTrace();}
}
}
catch (Exception e)
{
updatetrack("Server: Error!\n");
start2=false;
}
}
}
Related
I'm using C# for programming a network application. I'm using a thread to listen an IPEndPoint and answer it.
And another socket to send requests which is using in button handlers. I'm using the TCP protocol.
I've done it many times but today when I was testing it after a long time I understand my application can't connect well.
When I use telnet I can connect to my socket or when I create a test socket I can connect it by my application. There is no strange exception or error and I forward ports by Mono.Nat but problem is not ports because it can communicate with server or client side of itself.
Here is my listening socket code:
public static async void HandleIncomingConnection()
{
await ConfigConnection();
Socket Incomingsockresponde = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint LocalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), StandardPorts[0]);
string NetworkCommandString;
byte[] BytedNetworkString = new byte[1024];
byte[] BytedNetworkFile = new byte[1024 * 100000];
int Len, checker = 0, check = 0;
while(true)
{
try
{
check++;
Incomingsockresponde.Bind(LocalEndPoint);
Incomingsockresponde.Listen(1);
Incomingsockresponde = Incomingsockresponde.Accept();
MessageBox.Show("debug:\n Some remote host connected:" + Incomingsockresponde.RemoteEndPoint.ToString());
MessageBox.Show("Host flagged . . .", "Yeap!");
var mainp = new mainprivate();
mainp.Hstate = "Host not flagged";
try
{
//todo:log stuff
Len = Incomingsockresponde.Receive(BytedNetworkString);
NetworkCommandString = Encoding.ASCII.GetString(BytedNetworkString, 0, Len);
RespondeCommand(NetworkCommandString, Incomingsockresponde);
Incomingsockresponde.Disconnect(true);
}
catch (Exception err)
{
checker++;
MessageBox.Show("Something went wrong with this error:\n" + err.ToString(), "Woops!");
if (checker == 3)
{
MessageBox.Show("Host has some issues for connections", "Woops!");
var main2p = new mainprivate();
main2p.Hstate = "Host has some issues on connections";
return;
}
}
}
catch(Exception err)
{
MessageBox.Show("Something went wrong with this error:\n" + err.ToString(), "Woops!");
if(check == 3)
{
MessageBox.Show("Host not flagged . . .", "Woops!");
var main2p = new mainprivate();
main2p.Hstate = "Host not flagged";
return;
}
if(Incomingsockresponde.Connected == true)
Incomingsockresponde.Disconnect(true);
}
}
}
#endregion
[STAThread]
static void Main()
{
//debug:
MessageBox.Show("Here we go ports :\n" + "ResPort: " + ResPort + "-- - StreamPort:" + StreamPort + "-- - EmerPort:" + EmerPort);
Thread HandleIncomingConnectionThread = new Thread(new ThreadStart(HandleIncomingConnection));
HandleIncomingConnectionThread.Start();
connections[0] = "test";
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new welcome());
}
And this is my request code below:
try
{
Program.availsock.Connect(IPAddress.Parse(haddr[0]), Convert.ToInt16(haddr[1]));
}
catch (Exception err)
{
MessageBox.Show("Can't reach the host" + valstr);
//return;
Program.hostsn--;
addacchost(myKeys[i], valstr, new Size(944, 217), "Uavailable remote host");
goto endsock;
}
//connected
byte[] tmpmssg = new byte[1024];
tmpmssg = Encoding.ASCII.GetBytes(Program.hey);
Program.availsock.Send(tmpmssg);
int tmplng = Program.availsock.Receive(tmpmssg);
string rcdval = Encoding.ASCII.GetString(tmpmssg, 0, tmplng);
haddr = null;
Program.availsock.Close(0);
haddr = rcdval.Split('%');
if (!Program.supporteddistros.Contains(haddr[0]) || !Program.supportedversions.Contains(haddr[1]) || !Program.supportedtypes.Contains(haddr[2]))
{
MessageBox.Show("Unsupported remote host" + valstr);
//delete that from there
Program.oridndic.RemoveAt(checker - 1);
Program.hostsn--;
addacchost(myKeys[i], valstr, new Size(944, 217), "Unsupported remote host");
//acchost.Loadlbl = "Unsupported/Deleted";
//hosts2.Controls.Add(acchost);
//return;
goto endsock;
}
I check ports by netstat -ab and it was listening but it just received connections by telnet or my test socket not request side of my code or reverse my request side just sent request to my test socket.
Is this about my code structure?
Am I making a mistake?
Edit: I also defined a inbound rule for all ports and other stuff for windows firewall.
I'm so confused I never faced this situation I'm just looking for a clue.
Ok well that was just a wrong convert for port i did :
IPEndPoint ep = new IPEndPoint(IPAddress.Parse("0.0.0.0"), Convert.toInt16( port int here));
and it should be :
IPEndPoint ep = new IPEndPoint(IPAddress.Parse("0.0.0.0"), int.Parse(Port int here));
Thanks peoples dont help :/
I am trying to create a blockchain example where all clients work as a server and a client at once. I have a thread which constantly listens for incoming connections and when a client is accepted, it creates a thread which reads the incoming data and sends data aswell. It works one way, for example if just one server is started and I join to it as a client, but for example I want to start 3 instances and start a server on all 3 of them, and then I want to connect to instance 2 from instance 1 and so on... This is the code for acceping clients and the join, host function:
TcpClient Join()
{
int server_port = int.Parse(port.Text);
klient = new TcpClient();
try
{
klient.Connect("localhost", server_port);
if (klient.Connected) //Če se poveže
{
Console.WriteLine("Connected to server.");
myNetworkStream = klient.GetStream();
}
}
catch (Exception e)
{
}
return klient;
}
TcpListener Host()
{
int port = FreeTcpPort();
IPAddress ip_address = IPAddress.Parse("127.0.0.1"); //parsing ipja
TcpListener host = new TcpListener(ip_address, port);//ustvari listener
label1.Text = port.ToString();
try
{
host.Start();//zagon strežnika
Console.WriteLine("Server started...");
mine_button.Enabled = true;
Sprejemaj_cliente = new Thread(Cakaj_na_clienta);
Sprejemaj_cliente.Start(host);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
return host;
}
public void Cakaj_na_clienta(object argument)
{
TcpListener host = (TcpListener)argument;
try
{
while (true) //ČAKANJE NA POŠILJATELJA
{
Console.WriteLine("Waiting for client...");
TcpClient client = host.AcceptTcpClient();
klient = client;
MessageBox.Show("Client connected");
string odjemalec_IP = ((IPEndPoint)client.Client.RemoteEndPoint).Address.ToString();
int odjemalec_PORT = ((IPEndPoint)client.Client.RemoteEndPoint).Port;
Console.WriteLine("Povezal se je pošiljatelj na naslovu " + odjemalec_IP + ":" + odjemalec_PORT); //Zagon strežnika
myNetworkStream = klient.GetStream();
sync_thread = new Thread(Synchronize);
sync_thread.Start();
send_chain = new Thread(Send_Chain);
send_chain.Start();
}
}
catch (SocketException e)
{
}
}
I have an app on my android phone that sends a UDP packet with some information and I want to send this UDP packet to my Unity application. The android App works and sends the UDP packet (checked with wireshark) but somehow my C# script can't receive any. I googled and looked at similiar problems but none of them gave me an answer. I really don't know why it can't accept the packet.
I am broadcasting the UDP packet to make things easier but it doesn't seem to work. I also checked the ports.
Here is my C# code:
public class ControllerListener : MonoBehaviour
{
Thread receiveThread;
UdpClient client;
public int port;
public string lastReceivedUDPPacket = "";
public string allReceivedUDPPackets = "";
public void Start()
{
init();
}
// OnGUI
void OnGUI()
{
Rect rectObj = new Rect(40, 10, 200, 400);
GUIStyle style = new GUIStyle();
style.alignment = TextAnchor.UpperLeft;
GUI.Box(rectObj, "# UDPReceive\n127.0.0.1 " + port + " #\n"
+ "shell> nc -u 127.0.0.1 : " + port + " \n"
+ "\nLast Packet: \n" + lastReceivedUDPPacket
+ "\n\nAll Messages: \n" + allReceivedUDPPackets
, style);
}
public void Update()
{
}
// init
private void init()
{
print("UDPSend.init()");
// define port
port = 5678;
// status
print("Sending to 127.0.0.1 : " + port);
print("Test-Sending to this Port: nc -u 127.0.0.1 " + port + "");
receiveThread = new Thread(
new ThreadStart(ReceiveData));
receiveThread.IsBackground = true;
receiveThread.Start();
}
// receive thread
private void ReceiveData()
{
client = new UdpClient(port);
while (true)
{
try
{
// Bytes empfangen.
IPEndPoint anyIP = new IPEndPoint(IPAddress.Broadcast, 5678);
byte[] data = client.Receive(ref anyIP);
// Bytes mit der UTF8-Kodierung in das Textformat kodieren.
string text = Encoding.UTF8.GetString(data);
// Den abgerufenen Text anzeigen.
print(">> " + text);
// latest UDPpacket
lastReceivedUDPPacket = text;
Thread.Sleep(8);
Debug.Log("Hier");
// ....
allReceivedUDPPackets = allReceivedUDPPackets + text;
}
catch (Exception err)
{
print(err.ToString());
}
}
}
// getLatestUDPPacket
// cleans up the rest
public string getLatestUDPPacket()
{
allReceivedUDPPackets = "";
return lastReceivedUDPPacket;
}
void OnDisable()
{
if (receiveThread != null)
receiveThread.Abort();
client.Close();
}
}
I just want to know why doesn't my code get out from the .Receive(...) method even though a UDP packet is broadcasted.
Thanks in advance (my first post on this site)
cheers
Udpclient.Receive will block until a datagram arrives from a remote host.
So if it doesn't return it simply means nothing was received yet.
This can have multiple reasons.
Afaik for IPEndPoint you should probably rather use
IPEndPoint anyIP = new IPEndPoint(IPAddress.Any, 0);
Which means the sender can have any IP address and send from any port. You limited the sender address to Broadcast which will probably never be the case since the sender can not have a broadcast adress. Also the senders outgoing port might not match 5678. 0 allows the sender to send from any port.
Sidenote: Thread.Sleep is in milliseconds so using only 8 also looks a bit odd ;)
Im trying to make a Energy plant simulator and i like to simulate in my app few devices.
The idea is that the master request for something and the app ask to the needed slave and make something.
I just start using Nmodbus and all work fine with 1 device.
I tryed using SlaveId to ask for each device but when i read or write, i ever got all writed in the same Datastore.
The app and device run in localhost.
This is how i declare each device in the same network:
int port = 502;
IPAddress address = new IPAddress(new byte[] { 127, 0, 0, 1 });
// create and start the TCP slave
slaveTcpListener = new TcpListener(address, port);
slaveTcpListener.Start();
slave1 = ModbusTcpSlave.CreateTcp(1, slaveTcpListener);
slave1.DataStore = DataStoreFactory.CreateDefaultDataStore();
slave1.Listen();
slave2 = ModbusTcpSlave.CreateTcp(2, slaveTcpListener);
slave2.DataStore = DataStoreFactory.CreateDefaultDataStore();
slave2.Listen();
And this is how i request data of each device:
using (TcpClient client = new TcpClient("127.0.0.1", 502))
{
ModbusIpMaster master = ModbusIpMaster.CreateIp(client);
// read five input values
ushort startAddress = 0;
ushort numInputs = 10;
ushort[] inputs = master.ReadHoldingRegisters(1,startAddress, numInputs);
ushort[] inputs2 = master.ReadHoldingRegisters(2, startAddress, numInputs);
}
But the result is ever the Datastore of slave1.
Unfortunately, there is no way to run multiple slave devices, because slave.Listen() method includes infinite cycle:
public override void Listen()
{
while (true)
{
try
{
try
{
// read request and build message
byte[] frame = SerialTransport.ReadRequest();
IModbusMessage request = ModbusMessageFactory.CreateModbusRequest(frame);
if (SerialTransport.CheckFrame && !SerialTransport.ChecksumsMatch(request, frame))
{
string msg = $"Checksums failed to match {string.Join(", ", request.MessageFrame)} != {string.Join(", ", frame)}.";
Debug.WriteLine(msg);
throw new IOException(msg);
}
// only service requests addressed to this particular slave
if (request.SlaveAddress != UnitId)
{
Debug.WriteLine($"NModbus Slave {UnitId} ignoring request intended for NModbus Slave {request.SlaveAddress}");
continue;
}
// perform action
IModbusMessage response = ApplyRequest(request);
// write response
SerialTransport.Write(response);
}
catch (IOException ioe)
{
Debug.WriteLine($"IO Exception encountered while listening for requests - {ioe.Message}");
SerialTransport.DiscardInBuffer();
}
catch (TimeoutException te)
{
Debug.WriteLine($"Timeout Exception encountered while listening for requests - {te.Message}");
SerialTransport.DiscardInBuffer();
}
// TODO better exception handling here, missing FormatException, NotImplemented...
}
catch (InvalidOperationException)
{
// when the underlying transport is disposed
break;
}
}
That same limitation caused a problem for me, so I took over the NModbus4 project (now just NModbus):
https://github.com/NModbus/NModbus
public static async Task StartModbusSerialRtuSlaveNetwork()
{
using (SerialPort slavePort = new SerialPort("COM5"))
{
// configure serial port
slavePort.BaudRate = 19200;
slavePort.DataBits = 8;
slavePort.Parity = Parity.Even;
slavePort.StopBits = StopBits.One;
slavePort.Open();
//Create an instance of the ModbusFactory
IModbusFactory factory = new ModbusFactory();
//Create an adapter for the serial port
var adapter = new SerialPortAdapter(slavePort);
//Create the slave network
IModbusSlaveNetwork modbusSlaveNetwork = factory.CreateRtuSlaveNetwork(adapter);
//Create the slaves
IModbusSlave slave1 = factory.CreateSlave(1);
IModbusSlave slave2 = factory.CreateSlave(2);
//Add the slaves to the network
modbusSlaveNetwork.AddSlave(slave1);
modbusSlaveNetwork.AddSlave(slave2);
await modbusSlaveNetwork.ListenAsync();
await Task.Delay(1);
}
}
I am making a chat service for a game,
I am using a TCP listener an client for the account information, some sort of login service. I'm wondering if i can keep the socked the client connected to the server with, to check if he is still online, and keep sending him messages if he has new messages.
I already tried making a list of sockets for the login queue, but it disconnected the previous socket to to server as soon as i accepted a new socket.
byte[] usernameByte = new byte[100];
int usernameRecieved = s.Receive(usernameByte);
//guiController.setText(System.DateTime.Now + " Recieved Login...");
byte[] passByte = new byte[100];
int passRecieved = s.Receive(passByte);
//guiController.setText(System.DateTime.Now + " Recieved Password...");
string username = "";
string password = "";
for (int i = 0; i < usernameRecieved; i++)
username += (Convert.ToChar(usernameByte[i]));
for (int i = 0; i < passRecieved; i++)
password += (Convert.ToChar(passByte[i]));
if (DomainController.getInstance().checkAccount(username, password))
{
ASCIIEncoding asen = new ASCIIEncoding();
s.Send(asen.GetBytes("true"));
s.Send(asen.GetBytes("U are succesfully logged in, press enter to continue"));
guiController.setText(serverName,System.DateTime.Now+"");
guiController.setText(serverName, "Sent Acknowledgement - Logged in");
}
else
{
ASCIIEncoding asen = new ASCIIEncoding();
s.Send(asen.GetBytes("false"));
s.Send(asen.GetBytes("U are NOT logged in, press enter to continue"));
guiController.setText(serverName, System.DateTime.Now + "");
guiController.setText(serverName, "\nSent Acknowledgement - Not logged in");
}
This is the code i currently use to check the account information the user send me. Right after i send this the user dropd the connection and i move on to the next one.
I have tried making 1 list of seperate sockets and processing them one by one, but that failed because the previous socket's connection dropped, even tho it were 2 different machines that tried to connect.
Does anyone have a sollution / a way to save sockets, that I can use to make the program keep all the connections alive? so i can send a message from user 1 to user 2, and just use the socket they connected with? or do i need to add an id every time they make a connection?
EDIT
The client Code: (this is just a test client)
while (true)
{
TcpClient tcpclnt = new TcpClient();
Console.WriteLine("Connecting.....");
tcpclnt.Connect("xx.xxx.xxx.xx", 26862);
// use the ipaddress as in the server program
while(!(checkResponse(tcpclnt.GetStream())))
{
Thread.Sleep(1000);
}
Console.WriteLine("Connected");
Console.Write("Enter the string to be transmitted : ");
String str = Console.ReadLine();
if (str == "")
{
str = " ";
}
Stream stm = tcpclnt.GetStream();
ASCIIEncoding asen = new ASCIIEncoding();
byte[] ba = asen.GetBytes(str);
Console.WriteLine("Transmitting.....");
stm.Write(ba, 0, ba.Length);
Console.Write("Enter the string to be transmitted : ");
String str2 = Console.ReadLine();
if (str2 == "")
{
str2 = " ";
}
Stream stm2 = tcpclnt.GetStream();
ASCIIEncoding asen2 = new ASCIIEncoding();
byte[] ba2 = asen2.GetBytes(str2);
Console.WriteLine("Transmitting.....");
stm.Write(ba2, 0, ba2.Length);
if (str == "false")
{
blijvenWerken = false;
}
byte[] bb = new byte[100];
int k = stm.Read(bb, 0, 100);
for (int i = 0; i < k; i++)
Console.Write(Convert.ToChar(bb[i]));
byte[] bb2 = new byte[100];
int k2 = stm.Read(bb2, 0, 100);
Console.Write("\n");
for (int i = 0; i < k2; i++)
Console.Write(Convert.ToChar(bb2[i]));
Console.WriteLine("\n");
tcpclnt.Close();
Thread.Sleep(1000);
}
Server getting the sockets:
This bit of code is on the loginserver, its because i can only accept 1 socket every time to keep the connection alive, that i put queueCount on a maximum of 1.
I want to be able to make a list of Sockets that i accepted to add to a User account.
while (loginServerOn)
{
if (queueCount < 1)
{
if (loginServer.getLoginListener().Pending())
{
loginQueue.Add(loginServer.getSocket());
ASCIIEncoding asen = new ASCIIEncoding();
Socket s = loginQueue.First();
try
{
s.Send(asen.GetBytes("true"));
queueCount++;
}
catch
{
loginQueue.Remove(s);
}
}
}
}
The function that returns the accepted socket.
public Socket getSocket()
{
return myList.AcceptSocket();
}
EDIT: Essence of the question
I want to add the socked or client recieved to my Account object, so every connection has an Account its linked to, when i want to send a message to a certain account, it should send a message to the socked or client bound to that account, can you help/show me how i can achieve this?
This is still c# and sockets but my approach is different to yours.
I went with the concept of a "connectedCleint" which is similar in purpose to what you've called an account.
I have a class called ServerTerminal which is responsible for accepting and top level management of socket connections. In this i've got:
public Dictionary<long, ConnectedClient> DictConnectedClients =
new Dictionary<long, ConnectedClient>();
So this is my list of connected clients indexed by the sockethandle.
To accept connections i've got a routine:
public void StartListen(int port)
{
socketClosed = false;
IPEndPoint ipLocal = new IPEndPoint(IPAddress.Any, port);
listenSocket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
//bind to local IP Address...
//if ip address is allready being used write to log
try
{
listenSocket.Bind(ipLocal);
}
catch (Exception excpt)
{
// Deal with this.. write your own log code here ?
socketClosed = true;
return;
}
//start listening...
listenSocket.Listen(100); // Max 100 connections for my app
// create the call back for any client connections...
listenSocket.BeginAccept(new AsyncCallback(OnClientConnection), null);
}
So when a client connects it then fires off:
private void OnClientConnection(IAsyncResult asyn)
{
if (socketClosed)
{
return;
}
try
{
Socket clientSocket = listenSocket.EndAccept(asyn);
ConnectedClient connectedClient = new ConnectedClient(clientSocket, this, _ServerTerminalReceiveMode);
//connectedClient.MessageReceived += OnMessageReceived;
connectedClient.Disconnected += OnDisconnection;
connectedClient.dbMessageReceived += OndbMessageReceived;
connectedClient.ccSocketFaulted += ccSocketFaulted;
connectedClient.StartListening();
long key = clientSocket.Handle.ToInt64();
if (DictConnectedClients.ContainsKey(connectedClient.SocketHandleInt64))
{
// Already here - use your own error reporting..
}
lock (DictConnectedClients)
{
DictConnectedClients[key] = connectedClient;
}
// create the call back for any client connections...
listenSocket.BeginAccept(new AsyncCallback(OnClientConnection), null);
}
catch (ObjectDisposedException excpt)
{
// Your own code here..
}
catch (Exception excpt)
{
// Your own code here...
}
}
The crucial part of this for you is:
// create the call back for any client connections...
listenSocket.BeginAccept(new AsyncCallback(OnClientConnection), null);
This sets up the serverterminal to receive new connections.
Edit:
Cut down version of my connectedclient:
public class ConnectedClient
{
private Socket mySocket;
private SocketIO mySocketIO;
private long _mySocketHandleInt64 = 0;
// These events are pass through; ConnectedClient offers them but really
// they are from SocketIO
public event TCPTerminal_ConnectDel Connected
{
add
{
mySocketIO.Connected += value;
}
remove
{
mySocketIO.Connected -= value;
}
}
public event TCPTerminal_DisconnectDel Disconnected
{
add
{
mySocketIO.Disconnected += value;
}
remove
{
mySocketIO.Disconnected -= value;
}
}
// Own Events
public event TCPTerminal_TxMessagePublished TxMessageReceived;
public delegate void SocketFaulted(ConnectedClient cc);
public event SocketFaulted ccSocketFaulted;
private void OnTxMessageReceived(Socket socket, TxMessage myTxMessage)
{
// process your message
}
private void OnMessageSent(int MessageNumber, int MessageType)
{
// successful send, do what you want..
}
public ConnectedClient(Socket clientSocket, ServerTerminal ParentST)
{
Init(clientSocket, ParentST, ReceiveMode.Handler);
}
public ConnectedClient(Socket clientSocket, ServerTerminal ParentST, ReceiveMode RecMode)
{
Init(clientSocket, ParentST, RecMode);
}
private void Init(Socket clientSocket, ServerTerminal ParentST, ReceiveMode RecMode)
{
ParentServerTerminal = ParentST;
_myReceiveMode = RecMode;
_FirstConnected = DateTime.Now;
mySocket = clientSocket;
_mySocketHandleInt64 = mySocket.Handle.ToInt64();
mySocketIO = new SocketIO(clientSocket, RecMode);
// Register for events
mySocketIO.TxMessageReceived += OnTxMessageReceived;
mySocketIO.MessageSent += OnMessageSent;
mySocketIO.dbMessageReceived += OndbMessageReceived;
}
public void StartListening()
{
mySocketIO.StartReceiving();
}
public void Close()
{
if (mySocketIO != null)
{
mySocketIO.Close();
mySocketIO = null;
}
try
{
mySocket.Close();
}
catch
{
// We're closing.. don't worry about it
}
}
public void SendMessage(int MessageNumber, int MessageType, string Message)
{
if (mySocket != null && mySocketIO != null)
{
try
{
mySocketIO.SendMessage(MessageNumber, MessageType, Message);
}
catch
{
// mySocketIO disposed inbetween check and call
}
}
else
{
// Raise socket faulted event
if (ccSocketFaulted != null)
ccSocketFaulted(this);
}
}
}
}
Some useful links:
This is where I started:
http://vadmyst.blogspot.com.au/2008/01/how-to-transfer-fixed-sized-data-with.html
http://vadmyst.blogspot.com.au/2008/03/part-2-how-to-transfer-fixed-sized-data.html
And..
C# Sockets and Multithreading
Cause a connected socket to accept new messages right after .BeginReceive?
http://nitoprograms.blogspot.com.au/2009/04/tcpip-net-sockets-faq.html
http://www.codeproject.com/Articles/83102/C-SocketAsyncEventArgs-High-Performance-Socket-Cod
I can't post my entire solution just now; there is a flaw in my server code I need to debug; plus there are parts which my employer may not want published. But i based my code on what Vadym had for variable length messages.
When a server gets ready to accept TCP connections, it creates a new TCP socket, Bind() it to a port and uses the Listen() method. When a connection request comes in, the Listen() method returns a new socket that the server and client use for communication. The server and client can pass data back and forth using Send() and Receive() at this point. If the client disconnects, the server's Receive() terminates with 0 bytes of data.
If you want to wait for another connection request once you've accepted the first connection (i.e., while you are interacting with the first client) this can be done. At this point, you'll need to use something like threads or asynchronous methods so you can handle more than one connection. Basically, you will be able to Accept() connection requests from your listening socket.
Mike