c++ - Server won't connect to more than one client? -


the problem connects 1 client instead of two. can me figure out why?

server:

#include <sfml/system.hpp> #include <sfml/network.hpp> #include <iostream>  void sendinfo(void *userdata) {     sf::ipaddress* ip = static_cast<sf::ipaddress*>(userdata);     // print something...     while(true){         // create udp socket         sf::socketudp socket;          // create bytes send         char buffer[] = "sending info.";          // send data "192.168.0.2" on port 4567         if (socket.send(buffer, sizeof(buffer), *ip, 4444) != sf::socket::done)         {             // error...         }     } }  void receiveinfo(void *userdata) {     // print something...     while(true){         // create udp socket         sf::socketudp socket;          // bind (listen) port 4567         if (!socket.bind(4444))         {             // error...         }          char buffer[128];         std::size_t received;         sf::ipaddress sender;         unsigned short port;         if (socket.receive(buffer, sizeof(buffer), received, sender, port) != sf::socket::done)         {             // error...         }          // show address / port of sender         std::cout << buffer << std::endl;          socket.close();      } }  int main() {     sf::ipaddress client[2];     int connected = 0;     while(connected < 2){         // create udp socket         sf::socketudp socket;          // bind (listen) port 4567         if (!socket.bind(4444))         {             // error...         }          char buffer[128];         std::size_t received;         sf::ipaddress sender;         unsigned short port;         if (socket.receive(buffer, sizeof(buffer), received, sender, port) != sf::socket::done)         {             // error...         }          // show address / port of sender         client[connected] = sender;          socket.close();          sf::thread* send = new sf::thread(&sendinfo, &client[connected]);         sf::thread* receive = new sf::thread(&receiveinfo, &client[connected]);         // start !         send->launch();         receive->launch();         connected++;     }      while(true){      }      return exit_success; } 

client:

#include <sfml/system.hpp> #include <sfml/network.hpp> #include <iostream>  void sendinfo(void *userdata) {     // print something...     while(true){         // create udp socket         sf::socketudp socket;          // create bytes send         char buffer[] = "client sending info.";          // send data "192.168.0.2" on port 4567         if (socket.send(buffer, sizeof(buffer),  "127.0.0.1", 4444) != sf::socket::done)         {             // error...         }     } }  void receiveinfo(void *userdata) {     // print something...     while(true){         // create udp socket         sf::socketudp socket;          // bind (listen) port 4567         if (!socket.bind(4444))         {             // error...         }          char buffer[128];         std::size_t received;         sf::ipaddress sender;         unsigned short port;         if (socket.receive(buffer, sizeof(buffer), received, sender, port) != sf::socket::done)         {             // error...         }          // show address / port of sender         std::cout << buffer << std::endl;          socket.close();      } }  int main() {     // create udp socket     sf::socketudp socket;      // create bytes send     char buffer[] = "client joined.";      // send data "192.168.0.2" on port 4567     if (socket.send(buffer, sizeof(buffer), "127.0.0.1", 4444) != sf::socket::done)     {         // error...     }      sf::thread* send = new sf::thread(&sendinfo);     sf::thread* receive = new sf::thread(&receiveinfo);     // start !     send->launch();     receive->launch();       while(true){      }      return exit_success; } 

first things first: chat server or 'more typical' server?

if chat server, either need have list of sockets connected clients (you can connect udp sockets using connect() call, convenient, , helps reduce chances of spoofed peers) or list of client addresses can supply sendto() or sendmsg().

more 'typical' servers won't try send messages client except 1 made request: servers typically don't save anything clients, , instead use recvfrom() or recvmsg() peer's address use in later sendto() or sendmsg() calls.

also, protocols rely on 1 well known port; server uses 1 specific port convention, clients select whatever port open , free. ftp relies heavily on well-known ports on client-side well, , result gigantic pain tunnel through network address translation firewalls.

it isn't academic: both client and server attempting bind() port 4444. means need @ least two ip addresses on single machine test, or use virtualization software run entirely separate machine on same hardware, or have 2 machines available. it's more work needs be, , there's no reason clients care local port numbers:

server:

    // bind (listen) port 4567     if (!socket.bind(4444))     {         // error...     } 

client:

    // bind (listen) port 4567     if (!socket.bind(4444))     {         // error...     } 

poof! these 2 never run on same host without significant tricks. expect "it connects one" server or client connecting itself, without code fill in // error blocks, it'd tough tell sure.

(and while we're here, i'd take aside talk comments; comments re-state code aren't useful. you'll note of comments in fact wrong, referring wrong ips or ports. don't add information:

    // create udp socket     sf::socketudp socket; 

i know we're taught add comments, sadly we're not taught kind of comments add. comment in both programs i'd recommend keeping one, amended:

    // udp doesn't require listen or accept     if (!socket.bind(4444)) 

it isn't obvious reading code, , won't wrong when port number read out of environment variable, command line parameter, configuration file, or registry. (it might redundant in team of people familiar sockets api, might gold programmer not familiar differences between udp , tcp.)

good function names, variable names, etc., win on comments every time. end of aside. :)

and now, more minor nit-picking: thread handlers doing tasks this:

while(1) {     socket s;     bind s;     r = recv s;     print r;     close s; } 

this needless creation, binding, , closing, wasted energy, both computer's energy , (much more importantly) your energy. consider following 2 re-writings:

recv_thread() {     socket s;     bind s;     while (1) {         r = recv s;         print r;     }     close s; } 

or

recv_thread(s) {     while (1) {         r = recv s;         print r;     } } /* ... */ socket s; bind s; sf::thread* rt = new sf::thread(&recv_thread); rt->launch(s); 

the first option simple refactoring of existing code; keeps socket creation , destruction in thread function, moves loop invariants out of loop. code inside loop necessary.

the second option more drastic reworking: moves socket creation main thread, error-handling much easier, , thread function remote peer needs thread do. (if wanted change udp tcp, second option far easier easier 1 change -- threading code might not need modifications @ all.)

i hope helps. :)


Comments

Popular posts from this blog

c# - how to write client side events functions for the combobox items -

exception - Python, pyPdf OCR error: pyPdf.utils.PdfReadError: EOF marker not found -