Niezły burdel w kodzie :- ).
Z tego co widzę, ma to być chat, tak?
Do chata nie jest Ci potrzebna multipleksacja I/O selectem
. Wystarczy że po accepcie
zrobisz tak:
1.do tablicy zapiszesz deskryptor gniazda nowego klienta.
2.puscisz wątek nowego klienta.
3.jeśli klient otrzymał wiadomość to rozsyła ją do wszystkich gniazd w tablicy, jeśli sie rozłączył to z wątku klienta usuwasz jego deskryptor z tablicy
I wszystko :- )
Co co ctrl+c
to źle kombinujesz, wystarczy wywołać exit
, przy wywołaniu exit
sprzątaniem, czyli zamknięciem gniazd itp, zajmuje sie kernel, więc ten bool tam niepotrzebny, ew. dla pewności możesz ustawić sobie callbacki na std::atexit
i tam wszystko posprzątać.
Co do kodu, to (pomijając reszte)
Po kiego grzyba Ci te 2 while
?
to while((new_connect=accept(my_socket_server, (struct sockaddr*)&server_addr,&laddr_len))==0);
wykona się w przypadku pomyślnego połączenia tylko raz, i w przypadku błędu, również tylko raz. Bez sensu.
Co do wątków to zostaw pthread
a użyj <thread>
z c++11, oszczędzisz sobie wiele kłopotów.
I jak testujesz taki np.chat i nie ma konieczności pisania własnego klienta, to testuj za pomocą telnet
u, bo być może twój klient też jest lipny.
Masz tu przykład.
#include <iostream>
#include <string.h>
#include <netinet/in.h>
#include <algorithm>
#include <sys/socket.h>
#include <thread>
/** usage, telnet localhost 8888 **/
std::vector<int> clients;
void connection_handler(int);
int main()
{
sockaddr_in servaddr;
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(8888);
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
int yes = 1;
int listen_socket = socket(AF_INET, SOCK_STREAM, 0);
setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
bind(listen_socket, (sockaddr*)&servaddr, sizeof(servaddr));
listen(listen_socket, 10);
int newfd = 0;
while((newfd = accept(listen_socket, nullptr, nullptr)) > 0)
{
clients.push_back(newfd);
std::thread client_thread(connection_handler, newfd) ;
client_thread.detach();
}
}
void connection_handler(int client)
{
int rcv_bytes = 0, snd_bytes = 0;
std::array<char, 250> buff = {0};
while((rcv_bytes = recv(client, buff.data(), buff.size(), 0)) > 0)
{
for(auto cli : clients){
if(cli != client)
send(cli, buff.data(), strlen(buff.data()), 0);
}
memset(buff.data(), 0, buff.size());
}
clients.erase(std::find(clients.begin(), clients.end(), client));
std::cout << client << " drop..\n";
}