AREXPORT void ArNetServer::close(void) { std::list<ArSocket *>::iterator it; ArSocket *socket; if (!myOpened) return; myWantToClose = false; ArLog::log(ArLog::Normal, "ArNetServer shutting down server."); sendToAllClients("Shutting down server"); for (it = myConnectingConns.begin(); it != myConnectingConns.end(); ++it) { (*it)->writeString("Shutting down server"); } myOpened = false; while ((it = myConnectingConns.begin())!= myConnectingConns.end()) { socket = (*it); myConnectingConns.pop_front(); socket->close(); delete socket; } while ((it = myConns.begin()) != myConns.end()) { socket = (*it); myConns.pop_front(); socket->close(); delete socket; } myServerSocket.close(); }
void clientCloseCallback(ArServerClient * serverClient) { clientSock.close(); serverSock.close(); ss.runAsync(); cout << "client is closed, callback is done!" <<endl; }
AREXPORT void ArNetServer::runOnce(void) { ArSocket acceptingSocket; ArSocket *socket; char *str; std::list<ArSocket *> removeList; std::list<ArSocket *>::iterator it; ArArgumentBuilder *args = NULL; std::string command; if (!myOpened) { return; } lock(); // get any new sockets that want to connect while (myServerSocket.accept(&acceptingSocket) && acceptingSocket.getFD() >= 0) { acceptingSocket.setNonBlock(); // see if we want more sockets if (!myMultipleClients && (myConns.size() > 0 || myConnectingConns.size() > 0)) { // we didn't want it, so politely tell it to go away acceptingSocket.writeString("Conn refused."); acceptingSocket.writeString( "Only client allowed and it is already connected."); acceptingSocket.close(); ArLog::log(ArLog::Terse, "ArNetServer not taking multiple clients and another client tried to connect from %s.", acceptingSocket.getIPString()); } else { // we want the client so we put it in our list of connecting // sockets, which means that it is waiting to give its password socket = new ArSocket; socket->setLogWriteStrings(myLoggingDataSent); socket->transfer(&acceptingSocket); socket->writeString("Enter password:"******"Client connecting from %s.", socket->getIPString()); } } // now we read in data from our connecting sockets and see if // they've given us the password for (it = myConnectingConns.begin(); it != myConnectingConns.end(); ++it) { socket = (*it); // read in what the client has to say if ((str = socket->readString()) != NULL) { if (str[0] == '\0') continue; // now see if the word matchs the password if (myPassword == str) { ArLog::log(ArLog::Normal, "Client from %s gave password and connected.", socket->getIPString()); myConns.push_front(socket); removeList.push_front(socket); internalGreeting(socket); } else { socket->close(); myDeleteList.push_front(socket); ArLog::log(ArLog::Terse, "Client from %s gave wrong password and is being disconnected.", socket->getIPString()); } } // if we couldn't read a string it means we lost a connection else { ArLog::log(ArLog::Normal, "Connection to %s lost.", socket->getIPString()); socket->close(); myDeleteList.push_front(socket); } } // now we clear out the ones we want to remove from our connecting // clients list while ((it = removeList.begin()) != removeList.end()) { socket = (*it); myConnectingConns.remove(socket); removeList.pop_front(); } // now we read in data from our connecting sockets and see if // they've given us the password for (it = myConns.begin(); it != myConns.end() && myOpened; ++it) { socket = (*it); // read in what the client has to say while ((str = socket->readString()) != NULL) { // if this is null then there wasn't anything said if (str[0] == '\0') break; // make sure we read something // set up the arguments and then call the function for the // argument args = new ArArgumentBuilder; args->addPlain(str); //args->log(); parseCommandOnSocket(args, socket); delete args; args = NULL; } // if str was NULL we lost connection if (str == NULL) { ArLog::log(ArLog::Normal, "Connection to %s lost.", socket->getIPString()); socket->close(); myDeleteList.push_front(socket); } } // now we delete the ones we want to delete (we could do this above // but then it wouldn't be symetrical with above) while ((it = myDeleteList.begin()) != myDeleteList.end()) { socket = (*it); myConnectingConns.remove(socket); myConns.remove(socket); socket->close(); delete socket; myDeleteList.pop_front(); } if (myWantToClose) { close(); } unlock(); }
/// This should be its own thread here void *ArCentralManager::runThread(void *arg) { std::list<ArSocket *>::iterator sIt; std::list<std::string>::iterator nIt; std::list<ArCentralForwarder *>::iterator fIt; ArSocket *socket; std::string robotName; ArCentralForwarder *forwarder; ArNetPacket *packet; std::list<ArNetPacket *> addPackets; std::list<ArNetPacket *> remPackets; threadStarted(); while (getRunning()) { int numForwarders = 0; int numClients = 0; myDataMutex.lock(); // this is where the original code to add forwarders was before we // changed the unique behavior to drop old ones... std::list<ArCentralForwarder *> connectedRemoveList; std::list<ArCentralForwarder *> unconnectedRemoveList; for (fIt = myForwarders.begin(); fIt != myForwarders.end(); fIt++) { forwarder = (*fIt); numForwarders++; if (forwarder->getServer() != NULL) numClients += forwarder->getServer()->getNumClients(); bool connected = forwarder->isConnected(); bool removed = false; if (!forwarder->callOnce(myHeartbeatTimeout, myUdpHeartbeatTimeout, myRobotBackupTimeout, myClientBackupTimeout)) { if (connected) { ArLog::log(ArLog::Normal, "Will remove forwarder from %s", forwarder->getRobotName()); connectedRemoveList.push_back(forwarder); removed = true; } else { ArLog::log(ArLog::Normal, "Failed to connect to forwarder from %s", forwarder->getRobotName()); unconnectedRemoveList.push_back(forwarder); removed = true; } } if (!connected && !removed && forwarder->isConnected()) { ArLog::log(ArLog::Normal, "Adding forwarder %s", forwarder->getRobotName()); ArTime *newTime = new ArTime; newTime->setSec(0); myUsedPorts[forwarder->getPort()] = newTime; std::multimap<int, ArFunctor1<ArCentralForwarder *> *>::iterator it; for (it = myForwarderAddedCBList.begin(); it != myForwarderAddedCBList.end(); it++) { if ((*it).second->getName() == NULL || (*it).second->getName()[0] == '\0') ArLog::log(ArLog::Normal, "Calling unnamed add functor at %d", -(*it).first); else ArLog::log(ArLog::Normal, "Calling %s add functor at %d", (*it).second->getName(), -(*it).first); (*it).second->invoke(forwarder); } ArLog::log(ArLog::Normal, "Added forwarder %s", forwarder->getRobotName()); ArNetPacket *sendPacket = new ArNetPacket; sendPacket->strToBuf(""); sendPacket->uByte2ToBuf(forwarder->getPort()); sendPacket->strToBuf(forwarder->getRobotName()); sendPacket->strToBuf(""); sendPacket->strToBuf( forwarder->getClient()->getTcpSocket()->getIPString()); addPackets.push_back(sendPacket); // MPL added this at the same time as the changes for the deadlock that happened down below //myClientServer->broadcastPacketTcp(&sendPacket, "clientAdded"); } } while ((fIt = connectedRemoveList.begin()) != connectedRemoveList.end()) { forwarder = (*fIt); ArLog::log(ArLog::Normal, "Removing forwarder %s", forwarder->getRobotName()); std::multimap<int, ArFunctor1<ArCentralForwarder *> *>::iterator it; for (it = myForwarderRemovedCBList.begin(); it != myForwarderRemovedCBList.end(); it++) { if ((*it).second->getName() == NULL || (*it).second->getName()[0] == '\0') ArLog::log(ArLog::Normal, "Calling unnamed remove functor at %d", -(*it).first); else ArLog::log(ArLog::Normal, "Calling %s remove functor at %d", (*it).second->getName(), -(*it).first); (*it).second->invoke(forwarder); } ArLog::log(ArLog::Normal, "Called forwarder removed for %s", forwarder->getRobotName()); ArNetPacket *sendPacket = new ArNetPacket; sendPacket->strToBuf(""); sendPacket->uByte2ToBuf(forwarder->getPort()); sendPacket->strToBuf(forwarder->getRobotName()); sendPacket->strToBuf(""); sendPacket->strToBuf( forwarder->getClient()->getTcpSocket()->getIPString()); // MPL making this just push packets into a list to broadcast at the end since this was deadlocking //myClientServer->broadcastPacketTcp(&sendPacket, "clientRemoved"); remPackets.push_back(sendPacket); if (myUsedPorts.find(forwarder->getPort()) != myUsedPorts.end() && myUsedPorts[forwarder->getPort()] != NULL) myUsedPorts[forwarder->getPort()]->setToNow(); myForwarders.remove(forwarder); delete forwarder; connectedRemoveList.pop_front(); ArLog::log(ArLog::Normal, "Removed forwarder"); } while ((fIt = unconnectedRemoveList.begin()) != unconnectedRemoveList.end()) { forwarder = (*fIt); ArLog::log(ArLog::Normal, "Removing unconnected forwarder %s", forwarder->getRobotName()); if (myUsedPorts.find(forwarder->getPort()) != myUsedPorts.end() && myUsedPorts[forwarder->getPort()] != NULL) myUsedPorts[forwarder->getPort()]->setToNow(); myForwarders.remove(forwarder); delete forwarder; unconnectedRemoveList.pop_front(); ArLog::log(ArLog::Normal, "Removed unconnected forwarder"); } // this code was up above just after the lock before we changed // the behavior for unique names while ((sIt = myClientSockets.begin()) != myClientSockets.end() && (nIt = myClientNames.begin()) != myClientNames.end()) { socket = (*sIt); robotName = (*nIt); myClientSockets.pop_front(); myClientNames.pop_front(); ArLog::log(ArLog::Normal, "New forwarder for socket from %s with name %s", socket->getIPString(), robotName.c_str()); forwarder = new ArCentralForwarder(myClientServer, socket, robotName.c_str(), myClientServer->getTcpPort() + 1, &myUsedPorts, &myForwarderServerClientRemovedCB, myEnforceProtocolVersion.c_str(), myEnforceType); myForwarders.push_back(forwarder); } numClients += myRobotServer->getNumClients(); if (myRobotServer != myClientServer) numClients += myClientServer->getNumClients(); // end of code moved for change in unique behavior if (numClients > myMostClients) { ArLog::log(ArLog::Normal, "CentralManager: New most clients: %d", numClients); myMostClients = numClients; } if (numForwarders > myMostForwarders) myMostForwarders = numForwarders; if (numClients > myMostClients) { ArLog::log(ArLog::Normal, "CentralManager: New most forwarders: %d", numForwarders); myMostForwarders = numForwarders; } myRobotServer->internalSetNumClients(numForwarders + myClientSockets.size()); myDataMutex.unlock(); while (addPackets.begin() != addPackets.end()) { packet = addPackets.front(); myClientServer->broadcastPacketTcp(packet, "clientAdded"); addPackets.pop_front(); delete packet; } while (remPackets.begin() != remPackets.end()) { packet = remPackets.front(); myClientServer->broadcastPacketTcp(packet, "clientRemoved"); remPackets.pop_front(); delete packet; } ArUtil::sleep(1); //make this a REALLY long sleep to test the duplicate pending //connection code //ArUtil::sleep(20000); } threadFinished(); return NULL; }
void ArCentralManager::netServerSwitch(ArServerClient *client, ArNetPacket *packet) { char robotName[512]; std::string uniqueName; robotName[0] = '\0'; //printf("robotName before '%s'\n", robotName); packet->bufToStr(robotName, sizeof(robotName)); ArNetPacket sendPacket; /// acknowledge the switch client->sendPacketTcp(&sendPacket); ArSocket *clientSocket = new ArSocket; clientSocket->transfer(client->getTcpSocket()); client->tcpCallback(); client->forceDisconnect(true); // make the basis of the unique name if (robotName[0] != '\0') uniqueName = robotName; else uniqueName = client->getIPString(); //printf("Starting with '%s'\n", uniqueName.c_str()); myDataMutex.lock(); // walk through and make the name unique std::list<ArCentralForwarder *>::iterator fIt; ArCentralForwarder *forwarder; /* the old code that made the names unique bool nameIsUnique = false; while (!nameIsUnique) { nameIsUnique = true; for (fIt = myForwarders.begin(); fIt != myForwarders.end() && nameIsUnique; fIt++) { forwarder = (*fIt); if (strcasecmp(forwarder->getRobotName(), uniqueName.c_str()) == 0) nameIsUnique = false; } if (!nameIsUnique) uniqueName += "_"; } */ // the new code that drops the duplicates and replaces it with the same name for (fIt = myForwarders.begin(); fIt != myForwarders.end(); fIt++) { forwarder = (*fIt); if (strcasecmp(forwarder->getRobotName(), uniqueName.c_str()) == 0) { ArLog::log(ArLog::Normal, "ArCentralManager: Will drop old duplicate connection for %s", uniqueName.c_str()); forwarder->willReplace(); } } // remove any pending client duplicates while (removePendingDuplicateConnections(uniqueName.c_str())); // end of new code, though it also had reordering down below in the runthread myClientSockets.push_back(clientSocket); myClientNames.push_back(uniqueName); //printf("robotName after '%s'\n", robotName); // just print out the switch request name if its the same as it came in as if (strcmp(uniqueName.c_str(), robotName) == 0) ArLog::log(ArLog::Normal, "Got switch request from %s from %s", client->getIPString(), uniqueName.c_str()); // otherwise let them know what the unique name is if (strcmp(uniqueName.c_str(), robotName) != 0) ArLog::log(ArLog::Normal, "Got switch request from %s from %s that started as %s", client->getIPString(), uniqueName.c_str(), robotName); //printf("Ended with '%s'\n", uniqueName.c_str()); myDataMutex.unlock(); }
void* runThread(void*) { size_t strSize; // The socket objects: one for accepting new client connections, // and another for communicating with a client after it connects. // Open the server socket if (serverSock.open(VIDEO_PORT, ArSocket::TCP)) ArLog::log(ArLog::Normal, " Opened the server port %d.", VIDEO_PORT); else ArLog::log(ArLog::Normal, " Failed to open the server port: %s.", serverSock.getErrorStr().c_str()); if (serverSock.accept(&clientSock)) ArLog::log(ArLog::Normal, " Client has connected."); else ArLog::log(ArLog::Terse, " Error in accepting a connection from the client: %s.", serverSock.getErrorStr().c_str()); //.setCloseCallback(new ArGlobalFunctor1<ArNetPacket*>(&clientCloseCallback)); //serverSock.setCloseCallback(new ArGlobalFunctor1<ArNetPacket*>(&clientCloseCallback)); while(1) { //int clinetSocketStatus = serverSock.accept(&clientSock); // MODIFIED By Yang, Try to accept new client. // //if (clinetSocketStatus > 0){ // char buf[1024] = {0}; // int recievedInt = clientSock.read(buf, 1024, 0); // cout << recievedInt << endl; // while(true) // { /* send the grayscaled frame, thread safe */ mutex_video.lock(); if (is_data_ready) { int grayImgSize=gray_img.rows*gray_img.cols; //cout <<" Sending image to the client.grayImgSize= " << grayImgSize; if ((strSize = clientSock.write(gray_img.data, grayImgSize))==grayImgSize ) ;//ArLog::log(ArLog::Normal, " Sent image to the client.grayImgSize= %d", grayImgSize); // else // ArLog::log(ArLog::Normal, " Error in sending hello string to the client."); //ArLog::log(ArLog::Normal, " String Size: \"%d\"", strSize); is_data_ready = 0; } mutex_video.unlock(); //if(!clientSock.isOpen()) //{ // clientSock.close(); // ArLog::log(ArLog::Normal, " Socket to client closed."); // if (serverSock.accept(&clientSock)) // ArLog::log(ArLog::Normal, " Client has connected."); // else // ArLog::log(ArLog::Terse, " Error in accepting a connection from the client: %s.", serverSock.getErrorStr().c_str()); //} } //} //} // Now lets close the connection to the client clientSock.close(); ArLog::log(ArLog::Normal, " Socket to client closed."); // And lets close the server port //serverSock.close(); //ArLog::log(ArLog::Normal, " Server socket closed."); // Uninitialize Aria and exit the program //Aria::exit(0); } //end of runThread
int main() { // The string to send to the server. const char *strToSend="Hello Server"; // The buffer in which to recieve the hello from the server char buff[100]; // The size of the string the server sent size_t strSize; // The socket object ArSocket sock; // Initialize Aria. It is especially important to do // this on Windows, because it will initialize Window's // sockets system. Aria::init(); // Connect to the server ArLog::log(ArLog::Normal, "socketClientExample: Connecting to localhost TCP port 7777..."); if (sock.connect("localhost", 7777, ArSocket::TCP)) ArLog::log(ArLog::Normal, "socketClientExample: Connected to server at localhost TCP port 7777."); else { ArLog::log(ArLog::Terse, "socketClientExample: Error connecting to server at localhost TCP port 7777: %s", sock.getErrorStr().c_str()); return(-1); } // Read data from the socket. read() will block until // data is received. strSize=sock.read(buff, sizeof(buff)); // If the amount read is 0 or less, its an error condition. if (strSize > 0) { buff[strSize]='\0'; // Terminate the string with a NULL character: ArLog::log(ArLog::Normal, "socketClientExample: Server said: \"%s\"", buff); } else { ArLog::log(ArLog::Terse, "socketClientExample: Error in waiting/reading from the server."); Aria::exit(-1); return(-1); } // Send the string 'Hello Server' to the server. write() should // return the same number of bytes that we told it to write. Otherwise, // its an error condition. if (sock.write(strToSend, strlen(strToSend)) == strlen(strToSend)) ArLog::log(ArLog::Normal, "socketClientExample: Said hello to the server."); else { ArLog::log(ArLog::Terse, "socketClientExample: Error sending hello string to the server."); Aria::exit(-1); return(-1); } // Now close the connection to the server sock.close(); ArLog::log(ArLog::Normal, "socketClientExample: Socket to server closed."); // Uninitialize Aria and exit Aria::exit(0); return(0); }
void* RobotVideo::runThread(void* arg) { cvNamedWindow("Robot", CV_WINDOW_AUTOSIZE); moveWindow("Robot", 0, 0); // The buffer in which to receive the hello from the server //unsigned char buff[12]; unsigned char imgBuff[480*640]; //Mat imgRecieve(480,640,CV_8UC1); // The size of the string the server sent size_t strSize; // The socket object ArSocket sock; unsigned char *ptr; // Initialize Aria. It is especially important to do // this on Windows, because it will initialize Window's // sockets system. // Aria::init(); // Connect to the server //ArLog::log(ArLog::Normal, "socketClientExample: Connecting to localhost TCP port 7777..."); if (sock.connect(server_ip, ROBOT_VIDEO_PORT, ArSocket::TCP)) ArLog::log(ArLog::Normal, "Connected to server at %s TCP port 11000.", server_ip); else { ArLog::log(ArLog::Terse, "Error connecting to server at %s TCP port 11000: %s",server_ip, sock.getErrorStr().c_str()); //return(-1); } //---------------------------VideoWriter--------------------------------------- robotVideo.open("robot.avi" , CV_FOURCC('M','J','P','G') /* CV_FOURCC('P','I','M','1') */, 20/*inputVideo.get(CV_CAP_PROP_FPS)*/,Size(640, 480), false); if (!robotVideo.isOpened()) { cout << "Could not open the output video for write: " /*<< source*/ << endl; } while(1) { ptr = &imgBuff[0]; strSize = 0; while (strSize < 640 * 480) { //ArLog::log(ArLog::Normal, "socketClientExample: String Size: \"%d\"", strSize); strSize += sock.read(ptr, 2); ptr += 2; } ptr=robot_img.datastart; //ArLog::log(ArLog::Normal, "socketClientExample: String Size: \"%d\"", strSize); mutex_robotVideo.lock(); for (int i = 0,k = 0; i < robot_img.rows*robot_img.cols; i++) { *(ptr++) = imgBuff[k++]; } imshow("Robot", robot_img); robotVideo << robot_img; mutex_robotVideo.unlock(); waitKey(1);/*0)==27) break;*/ } sock.close(); //outputVideo.release(); // Now close the connection to the server ArLog::log(ArLog::Normal, "Socket to server closed."); destroyWindow("Robot"); // Uninitialize Aria and exit //Aria::exit(0); return NULL; }