I'm using C-style TCP sockets with send()
and recv()
. I have a connection running between user A and user B, where user A acts as a server and user B acts as a client.
I want to have a passive user C, which does not communicate anything, but receives data from user A. However, the new passive user C can join the session at any time. A might send C different packets than what it would send B.. I imagine it would be best for A-C to communicate on a different port than A-B
How can this connection be made (without threading, or the like) in an arbitrary point of communication?
edit still unsolved.
You could setup a listener that detects new connections, and mirror traffic to all open sockets. I recently wrote what I mean in C#: (i'll see whether I can quickly turn that into a C sample)
This example only accepts a fixed nr of incoming connections at the start, but it is dead easy to change that.
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Linq;
public class Demo
{
static IList<Socket> StartServer(int numberOfClients)
{
using(Socket main = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
main.Bind(new IPEndPoint(IPAddress.Any, 9050));
main.Listen(numberOfClients);
var clients = Enumerable
.Range(1,numberOfClients)
.Select(i => {
Console.WriteLine("Waiting for 1 more client...");
Socket client = main.Accept();
Console.WriteLine("Connected to {0}", client.RemoteEndPoint);
return client; })
.ToList();
main.Close();
return clients;
}
}
public static void Main()
{
var clients = StartServer(4);
while(clients.Count()>1) // still a conversation
{
var copyList = clients.ToList();
Console.WriteLine("Monitoring {0} sockets...", copyList.Count);
Socket.Select(copyList, null, null, 10000000);
foreach(Socket client in copyList)
{
byte[] data = new byte[1024];
int recv = client.Receive(data);
if (recv == 0)
{
Console.WriteLine("Client {0} disconnected.", client.RemoteEndPoint);
client.Close();
clients.Remove(client);
}
else
foreach (var other in clients.Except(new [] {client}))
other.Send(data, recv, SocketFlags.None);
}
}
Console.WriteLine("Last client disconnected, bye");
}
}
You can simply open 2 sockets on the server A, and bind them on 2 different ports. Then use select function on the 2 created socket file descriptors.
Select will return first time when one of the 2 clients make a connect. Remember that on server side, after accepting a connect, you should set the returned new file descriptor (with FD_SET) in order to make select listen to events that will happen on the new socket( which returned from accept).
精彩评论