There is a server that creates a separate stream for each new client.

while ((client_socket = accept(server_socket, (sockaddr*)&client_info, &client_addr_size))) { nclients++; HOSTENT *hst; hst = gethostbyaddr((char*)&client_info.sin_addr.S_un.S_addr, 4, AF_INET); printf("+%s [%s] new connect!\n", (hst) ? hst->h_name : "", inet_ntoa(client_info.sin_addr)); PRINTUSERS; DWORD thID; CreateThread(NULL, NULL, SexToClient, &client_socket, NULL, &thID); } 

The stream function itself sends certain messages to the client every n seconds. (All threads do not do this at the same time) I can’t figure out how to send a message to all clients at the same time. (I am sure that I am confused at all, and I have to go a completely different way). Actually the question is how to implement it?

  • one
    Typical broadcast is udp, not tcp, which obviously you (judging by accept) are using. Those. You can drop a packet with a broadcast IP address that will be accepted by all LAN computers in which someone listens to the port specified in this packet in the udp protocol. - avp

2 answers 2

I see two ways to solve this problem.

  1. Broadcast transmission. UDP is used to transmit such messages, not TCP. Then, clients will need to add reception and processing of UDP datagrams.
  2. Transfer of necessary data within the framework of the main exchange. In this case, you need to send a message to all threads running on the server, upon reception of which data is transmitted to clients.

    You can try the delegate and the standard callback. Here is an example.

     #include <assert.h> // Контейнер для хранения до 2-х аргументов. struct NIL {}; class IArguments { public: virtual ~IArguments() {} }; template< class T1 = NIL, class T2 = NIL > class Arguments : public IArguments { public: Arguments() {} public: Arguments( T1 i_arg1 ) : arg1( i_arg1 ) {} public: Arguments( T1 i_arg1, T2 i_arg2 ) : arg1( i_arg1 ), arg2( i_arg2 ) {} public: T1 arg1; T2 arg2; }; // Контейнер для хранения указателя на метод. class IContainer { public: virtual void Call( IArguments* ) = 0; }; template< class T, class M > class Container : public IContainer {}; // Специализация для метода без аргументов. template< class T > class Container< T, void (T::*)(void) > : public IContainer { typedef void (T::*M)(void); public: Container( T* c, M m ) : m_class( c ), m_method( m ) {} private: T* m_class; M m_method; public: void Call( IArguments* i_args ) { (m_class->*m_method)(); } }; // Специализация для метода с одним аргументом. template< class T, class A1 > class Container< T, void (T::*)(A1) > : public IContainer { typedef void (T::*M)(A1); typedef Arguments<A1> A; public: Container( T* c, M m ) : m_class( c ), m_method( m ) {} private: T* m_class; M m_method; public: void Call( IArguments* i_args ) { A* a = dynamic_cast< A* >( i_args ); assert( a ); if( a ) (m_class->*m_method)( a->arg1 ); } }; // Специализация для метода с двумя аргументами template< class T, class A1, class A2 > class Container< T, void (T::*)(A1,A2) > : public IContainer { typedef void (T::*M)(A1,A2); typedef Arguments<A1,A2> A; public: Container( T* c, M m ) : m_class( c ), m_method( m ) {} private: T* m_class; M m_method; public: void Call( IArguments* i_args ) { A* a = dynamic_cast< A* >( i_args ); assert( a ); if( a ) (m_class->*m_method)( a->arg1, a->arg2 ); } }; // Собственно делегат. class Delegate { public: Delegate() : m_container( 0 ) {} ~Delegate() { if( m_container ) delete m_container; } template< class T, class U > void Connect( T* i_class, U i_method ) { if( m_container ) delete m_container; m_container = new Container< T, U >( i_class, i_method ); } void operator()() { m_container->Call( & Arguments<>() ); } template< class T1 > void operator()( T1 i_arg1 ) { m_container->Call( & Arguments< T1 >( i_arg1 ) ); } template< class T1, class T2 > void operator()( T1 i_arg1, T2 i_arg2 ) { m_container->Call( & Arguments< T1, T2 >( i_arg1, i_arg2 ) ); } private: IContainer* m_container; }; class Victim { public: void Foo() {} void Bar( int ) {} }; int main() { Victim test_class; Delegate test_delegate; test_delegate.Connect( & test_class, & Victim::Foo ); test_delegate(); test_delegate.Connect( & test_class, & Victim::Bar ); test_delegate( 10 ); return 0; } 
    • Something I have a feeling that this is not the answer to that question ... - Harry