У меня есть 2 сокета на сервере и клиенте соответственно (где клиент подключается к серверу), на сервере у меня есть один класс, который содержит некоторую информацию о каждом клиенте, как IP , Сокет и ID .
Для каждого принятого соединения я добавляю последнего клиента, подключенного к этому List
, таким образом, у меня есть список (то есть объект) клиентов. А также каждый клиент добавляется в один ListView
, где назначается объект, относящийся к этому клиенту, в Tag свойство ListViewItem
. Это один из способов, который может помочь позже, если вы хотите отправить сообщение определенному клиенту.
Как вы можете видеть, List
клиентов ссылается только на 1 сокет, который прослушивает определенный номер порта. Теперь уже, когда у меня есть 2 сокета на каждой стороне (сервер и клиент), как я могу сделать, если я хочу отправить сообщение от второго Socket
сервера ко второму Socket
на клиенте? например, можно ли присвоить более 1 объекта Tag свойство ListViewItem
(только идея)?
Ниже приведен мой код (сервер, совместимый только с 1 Socket
и 1 объектом (List
клиента)):
Форма:
namespace mainForm
{
public partial class frmMain : Form
{
Listener server;
Thread start;
public frmMain()
{
InitializeComponent();
server = new Listener();
}
private void startToolStripMenuItem_Click(object sender, EventArgs e)
{
start = new Thread(listen);
start.Start();
}
private void listen()
{
server.BeginListen(101); // Select a port to listen
server.Received += new Listener.ReceivedEventHandler(server_Received);
server.Disconnected += new Listener.DisconnectedEventHandler(server_Disconnected);
}
private void server_Disconnected(Listener l, Info i)
{
Invoke(new _Remove(Remove), i);
}
private void server_Received(Listener l, Info i, string received)
{
string[] cmd = received.Split('|');
int inc;
for (inc = 0; inc < cmd.Length; inc++)
{
switch (cmd[inc].ToString())
{
case "CMD1":
Invoke(new _Add(Add), i, cmd[2] + " - " + cmd[3]);
break;
case "CMD2":
// Other code here
break;
}
}
}
private delegate void _Add(Info i, string computer);
private void Add(Info i, string computer)
{
string[] splitIP = i.RemoteAddress.Split(':');
ListViewItem item = new ListViewItem();
item.Text = i.ID.ToString();
item.SubItems.Add(splitIP[0]);
item.SubItems.Add(computer);
item.Tag = i;
lvConnections.Items.Add(item);
}
private delegate void _Remove(Info i);
private void Remove(Info i)
{
foreach (ListViewItem item in lvConnections.Items)
{
if ((Info)item.Tag == i)
{
item.Remove();
break;
}
}
}
private void disconnectToolStripMenuItem_Click(object sender, EventArgs e)
{
foreach (ListViewItem item in lvConnections.SelectedItems)
{
Info client = (Info)item.Tag;
client.Send("DISCONNECT" + Environment.NewLine);
}
}
Слушатель:
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
class Listener
{
Socket s;
public List<Info> clients;
public delegate void ReceivedEventHandler(Listener l, Info i, string received);
public event ReceivedEventHandler Received;
public delegate void DisconnectedEventHandler(Listener l, Info i);
public event DisconnectedEventHandler Disconnected;
bool listening = false;
public Listener()
{
clients = new List<Info>();
s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
}
public bool Running
{
get { return listening; }
}
public void BeginListen(int port)
{
s.Bind(new IPEndPoint(IPAddress.Any, port));
s.Listen(100);
s.BeginAccept(new AsyncCallback(AcceptCallback), s);
listening = true;
}
public void StopListen()
{
if (listening == true)
{
s.Close();
listening = false;
}
}
void AcceptCallback(IAsyncResult ar)
{
Socket handler = (Socket)ar.AsyncState;
Socket sock = handler.EndAccept(ar);
Info i = new Info(sock);
clients.Add(i);
sock.BeginReceive(i.buffer, 0, i.buffer.Length, SocketFlags.None, new AsyncCallback(ReadCallback), i);
handler.BeginAccept(new AsyncCallback(AcceptCallback), handler);
}
void ReadCallback(IAsyncResult ar)
{
Info i = (Info)ar.AsyncState;
try
{
int rec = i.sock.EndReceive(ar);
if (rec != 0)
{
string data = Encoding.UTF8.GetString(i.buffer, 0, rec);
Received(this, i, data);
}
else
{
Disconnected(this, i);
return;
}
i.sock.BeginReceive(i.buffer, 0, i.buffer.Length, SocketFlags.None, new AsyncCallback(ReadCallback), i);
}
catch (Exception ex)
{
Disconnected(this, i);
i.sock.Close();
clients.Remove(i);
}
}
}
Информация:
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
public class Info
{
public Socket sock;
public Guid ID;
public string RemoteAddress;
public byte[] buffer = new byte[8192];
public Info(Socket sock)
{
this.sock = sock;
ID = Guid.NewGuid();
RemoteAddress = sock.RemoteEndPoint.ToString();
}
public void Send(string data)
{
byte[] buffer = Encoding.UTF8.GetBytes(data);
sock.BeginSend(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback((ar) =>
{
sock.EndSend(ar);
}), buffer);
}
}
EDITION:
Вот то, что код выше уже делает =>
А вот как я хочу сделать (также работать с Сокет 02 в выбранном клиенте) =>