Cant put Accept() (CSocket) in its own thread - c++

I use blocking server-client to do a FTP homework.
But i got stuck when try to put Accept into a thread. (Everytime i run the CServer , it crahses and shut down)
Anyone know the answer or can suggest me sth else. i really appreciate it.
I really want to use blocking and CSocket ,so dont't suggest me non-blocking
I also took a look at p_thread, but i still won't if any chance my code works
void CServerDlg::OnBnClickedListen()
{
// TODO: Add your control notification handler code here
if (listen.Create(PORT, SOCK_STREAM, _T("127.0.0.1")) == 0) {
showMessage("Failed to init socket");
listen.GetLastError();
return;
}
else {
if (listen.Listen(1) == FALSE) {
showMessage("Can't listen to the port");
listen.Close();
return;
}
}
connectThread = thread(&CServerDlg::ThreadMain, this);
}
void CServerDlg::ThreadMain() {
int cnt = -1;
CSocket* client;
while (1)
{
client = new CSocket();
if (listen.Accept(*client)) // it crashes everytime i got here
{
cnt++;
char * id = Converter::StringToChar(Converter::NumberToString(*client));
clients.push_back(client);
ClientId.push_back(id);
showMessage("Found a connection with client " + Converter::CharToString(id));
/*
Thread here
*/
threads.push_back(thread(&CServerDlg::ThreadProc, this, cnt));
}
else break;
}
}

Related

Socket Handle Read Is never read In Ns3

I stayed many days to find where the error is and I'm stuck.Can anyone help me please.
MY application is a clustering program in NS3 that was written from one else and free to anyone.
The program is run and no errors and print messages but always the number of neighbors in every Cluster Head CH is zero, this mean that the hellow messages are not reach every node and every node consider itself as cluster head because it dosn't see any neighbor node!. every node (vehicle) has two sockets one for send data m_socket and one for listening m_socketlistening, the code is:
if (!m_socket)
{
// TypeId::LookupByName ("ns3::UdpSocketFactory
TypeId m_tid = TypeId::LookupByName("ns3::UdpSocketFactory");
//m_socket = Socket::CreateSocket(GetNode() , TypeId::LookupByName("ns3::UdpSocketFactory"));
m_socket = Socket::CreateSocket(GetNode(), m_tid);
// i added the down line
// InetSocketAddress remote = InetSocketAddress(Ipv4Address::GetBroadcast(),80);
if (Inet6SocketAddress::IsMatchingType(m_peer))
{
m_socket->Bind6();
}
else if (InetSocketAddress::IsMatchingType(m_peer)
|| PacketSocketAddress::IsMatchingType(m_peer))
{
m_socket->Bind();
}
m_socket->SetAllowBroadcast(true);
m_socket->ShutdownRecv();
m_socket->SetConnectCallback(
MakeCallback(&V2vControlClient::ConnectionSucceeded, this),
MakeCallback(&V2vControlClient::ConnectionFailed, this));
//m_socket->Connect(Ipv4Address::GetBroadcast());
m_socket->Connect(m_peer);
}
now this is a part pf the listening socket creation
if (!m_socketListening)
{
NS_LOG_UNCOND("\n ...creating socket muhsen...");
m_socketListening = Socket::CreateSocket(GetNode(), m_tidListening);
m_socketListening->Bind(m_peerListening);
m_socketListening->Listen();
m_socketListening->ShutdownSend();
if (addressUtils::IsMulticast(m_peerListening))
{
Ptr<UdpSocket> udpSocket = DynamicCast<UdpSocket>(m_socketListening);
if (udpSocket)
{
// equivalent to setsockopt (MCAST_JOIN_GROUP)
udpSocket->MulticastJoinGroup(0, m_peerListening);
}
else
{
NS_FATAL_ERROR("Error: joining multicast on a non-UDP socket");
}
}
}
m_socketListening->SetRecvCallback(MakeCallback(&V2vControlClient::HandleRead, this));
m_socketListening->SetAcceptCallback(
MakeNullCallback<bool, Ptr<Socket>, const Address &>(),
MakeCallback(&V2vControlClient::HandleAccept, this));
m_socketListening->SetCloseCallbacks(
MakeCallback(&V2vControlClient::HandlePeerClose, this),
MakeCallback(&V2vControlClient::HandlePeerError, this));
void V2vControlClient::HandleRead (Ptr<Socket> socket)
{
NS_LOG_UNCOND("\n this message is never executed..");
NS_LOG_FUNCTION (this << socket);
Ptr<Packet> packet;
Address from;
while ((packet = socket->RecvFrom(from)))
{
if (packet->GetSize() == 0)
{ //EOF
break;
}
When i run the application the first statement after the HandleRead Function which is
NS_LOG_UNCOND("\n this message is never executed..");
is never printed when run the program, this means that the handle read is never executed.
Any help is very appreciate!

C++ GRPC Async Bidirectional Streaming - How to tell when a client sent a message?

There is zero documentation how to do an async bidirectional stream with grpc. I've made guesses by piecing together the regular async examples with what I found in peope's github.
With the frankestein code I have, I cannot figure out how to tell when a client sent me a message. Here is the procedure I have running on its own thread.
void GrpcStreamingServerImpl::listeningThreadProc()
{
try
{
// I think we make a call to the RPC method and wait for others to stream to it?
::grpc::ServerContext context;
void * ourOneAndOnlyTag = reinterpret_cast<void *>(1); ///< Identifies the call we are going to make. I assume we can only handle one client
::grpc::ServerAsyncReaderWriter<mycompanynamespace::OutputMessage,
mycompanynamespace::InputMessage>
stream(&context);
m_service.RequestMessageStream(&context, &stream, m_completionQueue.get(), m_completionQueue.get(), ourOneAndOnlyTag);
// Now I'm going to loop and get events from the completion queue
bool keepGoing = false;
do
{
void* tag = nullptr;
bool ok = false;
const std::chrono::time_point<std::chrono::system_clock> deadline(std::chrono::system_clock::now() +
std::chrono::seconds(1));
grpc::CompletionQueue::NextStatus nextStatus = m_completionQueue->AsyncNext(&tag, &ok, deadline);
switch(nextStatus)
{
case grpc::CompletionQueue::NextStatus::TIMEOUT:
{
keepGoing = true;
break;
}
case grpc::CompletionQueue::NextStatus::GOT_EVENT:
{
keepGoing = true;
if(ok)
{
// This seems to get called if a client connects
// It does not get called if we didn't call 'RequestMessageStream' before the loop started
// TODO - How do we tell when the client send us a messages?
// TODO - How do we know if they are just connecting?
// TODO - How do we get the message client sent?
// The tag corresponds to the request we made
if(tag == reinterpret_cast<void *>(1))
{
// SNIP successful writing of a message
stream.Write(*(outputMessage.get()), reinterpret_cast<void*>(2));
}
else if(tag == reinterpret_cast<void *>(2))
{
// This is telling us the message we sent was completed
}
else
{
// TODO - I dunno what else it can be
}
}
break;
}
case grpc::CompletionQueue::NextStatus::SHUTDOWN:
{
keepGoing = false;
break;
}
}
} while(keepGoing);
// Completion queue was shutdown
}
catch(std::exception& e)
{
QString errorMessage(
QString("An std::exception was caught in the listening thread. Exception message: %1").arg(e.what()));
m_backPointer->onImplError(errorMessage);
}
catch(...)
{
QString errorMessage("An exception of unknown type, was caught in the listening thread.");
m_backPointer->onImplError(errorMessage);
}
}
Setup looked like this
// Start up the grpc service
grpc::ServerBuilder builder;
builder.RegisterService(&m_service);
builder.AddListeningPort(endpoint.toStdString(), grpc::InsecureServerCredentials());
m_completionQueue = builder.AddCompletionQueue();
m_server = builder.BuildAndStart();
// Start the listening thread
m_listeningThread = QThread::create(&GrpcStreamingServerImpl::listeningThreadProc, this);

How i can still use Accept in while loop to accept new clients,but also want to turn of the server whenever i want

I have a homework about FTP using CSocket in C++.I use Mfc Dialog-based as interface for my application.Using multithreading to handle multi-clients (1 server - many clients). I use a button called "Listen".Everytime i hit the button,server start to listen. But the problem here,i put the Accecpt in a loop to handle muti-clients (each clients will go in a seperate thread), but now i cannot close the server-dialog whenever i want.It stucks in the "Listen" button forever.Can you give me some suggest to make it works.I did some research myself.I tried some techniques but it didn't work.
Thank you.
Please dont tell me about Select or Poll, I am using Windows not Linux.
I want to keep CSocket ,not Winsock. I tried to close listen in another thread ,but it didn't work.
void CServerDlg::OnBnClickedListen()
{
// TODO: Add your control notification handler code here
if (listen.Create(PORT, SOCK_STREAM, _T("127.0.0.1")) == 0) {
showMessage("Failed to init socket");
listen.GetLastError();
return;
}
else {
if (listen.Listen(1) == FALSE) {
showMessage("Can't listen to the port");
listen.Close();
return;
}
}
int cnt = -1;
CSocket* client;
while (1)
{
client = new CSocket();
if (listen.Accept(*client))
{
cnt++;
char * id = Converter::StringToChar(Converter::NumberToString(*client));
clients.push_back(client);
ClientId.push_back(id);
showMessage("Found a connection with client " + Converter::CharToString(id));
/*
Thread here
*/
threads.push_back(thread(&CServerDlg::ThreadProc, this, cnt));
}
else break;
}
listen.Close();
for (int i = 0; i < clients.size(); i++)
{
if (clients[i] != NULL)
{
clients[i]->Close();
}
}
clients.clear();
}
```
void CServerDlg::OnBnClickedCancel()
{
// TODO: Add your control notification handler code here
// i want every time i click 'cancel; button theaplcaton will clsoe
}
```

Thread does not do anything

I try to use a thread to tell the user the COM port for serial communication he entered was wrong. I have a thread class which tries to establish the connection and a function in my main, that should tell the user.
The compiler does not complain, but my program never enters the function. Maybe anyone can spot the mistake I made.
main.cpp:
WindowsDgpsGUIFrame::WindowsDgpsGUIFrame(wxWindow* parent,wxWindowID id)
{
...
Bind(wxEVT_THREAD, &WindowsDgpsGUIFrame::onConnectionFailed, this, wxID_EXIT);
...
}
void WindowsDgpsGUIFrame::OnButtonStartClick(wxCommandEvent& event)
{
NavigationThread* navigationThread = new NavigationThread(this, m_usedVariables);
m_navigationThread = navigationThread;
wxThreadError err = m_navigationThread->Create();
if(err != wxTHREAD_NO_ERROR)
{
StaticStatusText->Enable();
StaticStatusText->SetLabel("Could not create NavigationThread.");
}
else{
StaticStatusText->SetLabel("Thread created");
}
err = m_navigationThread->Run();
if(err != wxTHREAD_NO_ERROR)
{
StaticStatusText->SetLabel("Could not run thread.");
}
}
void WindowsDgpsGUIFrame::onConnectionFailed(wxThreadEvent& event)
{
StaticConnectionText->SetLabel(event.GetString());
}
thread.cpp:
wxThread::ExitCode NavigationThread::Entry()
{
Serial serial;
int resultGnss = serial.Open(m_gnssPort, STANDARD_BAUDRATE);
wxThreadEvent event(wxEVT_THREAD, wxID_RETRY);
if(resultGnss != 0)
{
event.SetString("Connection to GNSS box not possible. Try with another COM port.");
m_parent->GetEventHandler()->AddPendingEvent(event);
}
else{
event.SetString("Connection successful");
m_parent->GetEventHandler()->AddPendingEvent(event);
}
return 0;
}
The thread gets created and starts running, but even though the event is thrown in the thread the program never reaches onConnectionFailed().

C++ select stops accepting connections

I'm trying to make a select-server in order to receive connection from several clients (all clients will connect to the same port).
The server accepts the first 2 clients, but unless one of them disconnects, it will not accept a new one.
I'm starting to listen the the server port like this:
listen(m_socketId, SOMAXCONN);
and using the select command like this:
int selected = select(m_maxSocketId + 1, &m_socketReadSet, NULL, NULL, 0);
I've added some code.
bool TcpServer::Start(char* ipAddress, int port)
{
m_active = true;
FD_ZERO(&m_socketMasterSet);
bool listening = m_socket->Listen(ipAddress, port);
// Start listening.
m_maxSocketId = m_socket->GetId();
FD_SET(m_maxSocketId, &m_socketMasterSet);
if (listening == true)
{
StartThread(&InvokeListening);
StartReceiving();
return true;
}
else
{
return false;
}
}
void TcpServer::Listen()
{
while (m_active == true)
{
m_socketReadSet = m_socketMasterSet;
int selected = select(m_maxSocketId + 1, &m_socketReadSet, NULL, NULL, 0);
if (selected <= 0)
continue;
bool accepted = Accept();
if (accepted == false)
{
ReceiveFromSockets();
}
}
}
bool TcpServer::Accept()
{
int listenerId = m_socket->GetId();
if (FD_ISSET(listenerId, &m_socketReadSet) == true)
{
struct sockaddr_in remoteAddr;
int addrSize = sizeof(remoteAddr);
unsigned int newSockId = accept(listenerId, (struct sockaddr *)&remoteAddr, &addrSize);
if (newSockId == -1) // Invalid socket...
{
return false;
}
if (newSockId > m_maxSocketId)
{
m_maxSocketId = newSockId;
}
m_clientUniqueId++;
// Remembering the new socket, so we'll be able to check its state
// the next time.
FD_SET(newSockId, &m_socketMasterSet);
CommEndPoint remote(remoteAddr);
CommEndPoint local = m_socket->GetLocalPoint();
ClientId* client = new ClientId(m_clientUniqueId, newSockId, local, remote);
m_clients.Add(client);
StoreNewlyAcceptedClient(client);
char acceptedMsg = CommInternalServerMsg::ConnectionAccepted;
Server::Send(CommMessageType::Internal, client, &acceptedMsg, sizeof(acceptedMsg));
return true;
}
return false;
}
I hope it's enough :)
what's wrong with it?
The by far most common error with select() is not re-initializing the fd sets on every iteration. The second, third, and forth arguments are updated by the call, so you have to populate them again every time.
Post more code, so people can actually help you.
Edit 0:
fd_set on Windows is a mess :)
It's not allowed to copy construct fd_set objects:
m_socketReadSet = m_socketMasterSet;
This combined with Nikolai's correct statement that select changes the set passed in probably accounts for your error.
poll (On Windows, WSAPoll) is a much friendlier API.
Windows also provides WSAEventSelect and (Msg)WaitForMultipleObjects(Ex), which doesn't have a direct equivalent on Unix, but allows you to wait on sockets, files, thread synchronization events, timers, and UI messages at the same time.