Timeout on recvfrom ( winsock2 & udp ) - c++

I'm trying to implement a timeout on the recvfrom() function.
To do so, I use the select() function. I take the code from the great Internet, but don't know why, my program crash when I use it.
I launch this server in athread if that coudl help.
Here's what I try to do :
...
// Setup timeval variable
timeval timeout;
timeout.tv_sec = 5;
timeout.tv_usec = 0;
// Setup fd_set structure
fd_set fds;
FD_ZERO(&fds);
FD_SET(id_de_la_socket, &fds);
// Return value:
// -1: error occurred
// 0: timed out
// > 0: data ready to be read
int retval = select(id_de_la_socket+1, &fds, NULL, NULL, &timeout);
if(retval == -1){
printf("Error");
return NULL;
}
else if(retval == 0){
printf("Timeout");
return NULL;
}
else{
nombre_de_caractere=recvfrom(id_de_la_socket,buffer,1515,/*MSG_PARTIAL*/0,(struct sockaddr*)&information_sur_la_source,&tempo);
...
Before trying to implement the timeout, everything works fine, my recvfrom() was in block mode. So I think the problem come from this code that I add. Maybe it's a parameter of a function that I don't understand well.
Thanks for your help.
EDIT : Full code :
#include "serveur.h"
#include <unistd.h>
#include <fcntl.h>
serveur::serveur()
{
}
StructureSupervision::T_StructureSupervision* serveur::receiveDataUDP(){
WSADATA initialisation_win32;
int erreur;
int tempo;
int nombre_de_caractere;
char buffer[65535];
SOCKET id_de_la_socket;
SOCKADDR_IN information_sur_la_source;
erreur=WSAStartup(MAKEWORD(2,2),&initialisation_win32);
if (erreur!=0)
printf("\nDesole, je ne peux pas initialiser Winsock du a l'erreur : %d %d",erreur,WSAGetLastError());
else
printf("\nWSAStartup : OK");
id_de_la_socket=socket(AF_INET,SOCK_DGRAM,0);
if (id_de_la_socket==INVALID_SOCKET)
printf("\nDesole, je ne peux pas creer la socket du a l'erreur : %d",WSAGetLastError());
else
printf("\nsocket : OK");
information_sur_la_source.sin_family=AF_INET;
information_sur_la_source.sin_addr.s_addr = inet_addr("10.100.13.129"); // Ecoute sur toutes les IP locales
information_sur_la_source.sin_port=htons(4000); // Ecoute sur le port 4000
erreur=bind(id_de_la_socket,(struct sockaddr*)&information_sur_la_source,sizeof(information_sur_la_source));
if (erreur!=0)
printf("\nDesole, je ne peux pas ecouter ce port : %d %d",erreur,WSAGetLastError());
else
printf("\nbind : OK \n");
tempo=sizeof(information_sur_la_source); // Passe par une variable afin d'utiliser un pointeur
// Setup timeval variable
timeval timeout;
timeout.tv_sec = 5;
timeout.tv_usec = 0;
// Setup fd_set structure
fd_set fds;
FD_ZERO(&fds);
FD_SET(id_de_la_socket, &fds);
// Return value:
// -1: error occurred
// 0: timed out
// > 0: data ready to be read
ULONG NonBlock = 1; ioctlsocket(id_de_la_socket, FIONBIO, &NonBlock);
int retval = select(id_de_la_socket+1, &fds, NULL, NULL, &timeout);
if(retval == -1){
printf("Error");
return NULL;
}
else if(retval == 0){
printf("Timeout");
return NULL;
}
else{
nombre_de_caractere=recvfrom(id_de_la_socket,buffer,1515,/*MSG_PARTIAL*/0,(struct sockaddr*)&information_sur_la_source,&tempo);
buffer[nombre_de_caractere]=0; // Permet de fermer le tableau apr�s le contenu des data, car la fonction recvfrom ne le fait pas
//printf("\nVoici les donnees : %s",buffer);
StructureSupervision::T_StructureSupervision *structureReception = (StructureSupervision::T_StructureSupervision *) buffer;
std::cout << "Voici le numero de Statut Ground Flight : " << structureReception->SystemData._statutGroundFlight;
erreur=closesocket(id_de_la_socket);
if (erreur!=0)
printf("\nDesole, je ne peux pas liberer la socket du a l'erreur : %d %d",erreur,WSAGetLastError());
else
printf("\nclosesocket : OK");
// ********************************************************
// Quitte proprement le winsock ouvert avec la commande WSAStartup
// ********************************************************
erreur=WSACleanup(); // A appeler autant de fois qu'il a �t� ouvert.
if (erreur!=0)
printf("\nDesole, je ne peux pas liberer winsock du a l'erreur : %d %d",erreur,WSAGetLastError());
else
printf("\nWSACleanup : OK");
return structureReception;
}
}

Thanks for your help, the problem was : This program runs in a loop, so I was opening and closing the socket at the wrong time.

Related

How to set the PC system time in Windows using VS C++ 2013

I am trying to set over time my PC time in Windows in C++. It doesn't work.
I already run my project as administrator.
I asked some privileges to effcetion this task.
But nothing, etc...
Could you have some ideas about it ?
Here is my code :
#include <windows.h>
#include <stdio.h>
#include <strsafe.h>
using namespace std;
void main()
{
SYSTEMTIME st;
ZeroMemory(&st, sizeof(st));
HANDLE hToken;
TOKEN_PRIVILEGES tkp;
// Enable the required privilege
OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY | TOKEN_ALL_ACCESS, &hToken);
LookupPrivilegeValue(NULL, SE_SYSTEMTIME_NAME, &tkp.Privileges[0].Luid);
tkp.PrivilegeCount = 1; // valider deux privileges , tkp contient les parametres de chaque privilege
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; // je valide le privilege 1
AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0); // pour valider ou desactiver les privileges dans un acces precis.
// LookupPrivilegeValue(NULL, SE_TIME_ZONE_NAME, &tkp.Privileges[1].Luid);
// tkp.Privileges[1].Attributes = SE_PRIVILEGE_ENABLED; // je valide le privilege 2
// Set system time
st.wHour = 15;
st.wMinute = 15;
SetSystemTime(&st);
GetSystemTime(&st);
printf("The system time is: %02d:%02d\n", st.wHour, st.wMinute);
tkp.Privileges[0].Attributes = 0;
AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
system("pause");
}

C++ CInternetSession connexion lost

I use CInternetSession to get and post request. But when a connexion time out occurs, I lost the connexion and I always get invalid server request error, I don't understand why. Moreover, there is also a memory leak.
#include "stdafx.h"
#include "httpConnexion.h"
#include "TSException.h"
ChttpConnexion::ChttpConnexion()
: CInternetSession(AfxGetAppName(), INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, NULL, INTERNET_FLAG_DONT_CACHE)
, m_lastRequest()
{
SetOption(INTERNET_OPTION_CONNECT_TIMEOUT, 10000);
SetOption(INTERNET_OPTION_RECEIVE_TIMEOUT, 10000);
m_bAttente = true;
}
ChttpConnexion::~ChttpConnexion()
{
}
std::string ChttpConnexion::sendRequest(const std::string& strUrl)
{
DWORD dwServiceType;
CString strServerName;
CString strObject;
INTERNET_PORT nPort;
AfxParseURL(strUrl.c_str(), dwServiceType, strServerName, strObject, nPort);
CString strHeaders = _T("User-Agent: User-Agent=Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\nAccept-Language: fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7\r\nConnection: keep-alive\r\nContent-Type: application/x-www-form-urlencoded");
CString strTmp = "", strResult = "";
CHttpConnection* pHttpConnexion = NULL;
CHttpFile* pHttpFile = NULL;
try
{
//Creation de la connexion Http
pHttpConnexion = GetHttpConnection(strServerName, INTERNET_FLAG_RELOAD | INTERNET_FLAG_DONT_CACHE, nPort, NULL, NULL);
//Creation de la requete GET
pHttpFile = pHttpConnexion->OpenRequest(CHttpConnection::HTTP_VERB_GET, strObject, NULL, 1, NULL, NULL, INTERNET_FLAG_RELOAD | INTERNET_FLAG_DONT_CACHE);
//Envoi de la requéte
BOOL bRequestSend = pHttpFile->SendRequest(strHeaders);
CString headers;headers.Empty();
DWORD dwRet;
pHttpFile->QueryInfo(HTTP_QUERY_RAW_HEADERS_CRLF,headers);
pHttpFile->QueryInfoStatusCode(dwRet);
//Lecture du résultat
while ( pHttpFile->ReadString(strTmp))
{
strResult += strTmp;
}
//Fermeture de la requéte
pHttpFile->Close();
//Fermeture de la connexion
pHttpConnexion->Close();
//Suppression des objets
if (pHttpFile != NULL)
delete pHttpFile;
if (pHttpConnexion != NULL)
delete pHttpConnexion;
}
catch(CInternetException* exp)
{
exp->Delete();
//Fermeture de la requéte
if (pHttpFile != NULL)
{
pHttpFile->Close();
delete pHttpFile;
}
//Fermeture de la connexion
if (pHttpConnexion != NULL)
{
pHttpConnexion->Close();
delete pHttpConnexion;
}
throw CTSException("sendRequest");
}
return strResult.GetString();
}
std::string ChttpConnexion::postRequest(const std::string& strUrl, const std::string& postData)
{
DWORD dwServiceType;
CString strServerName;
CString strObject;
INTERNET_PORT nPort;
AfxParseURL(strUrl.c_str(), dwServiceType, strServerName, strObject, nPort);
CString strHeaders = _T("User-Agent: User-Agent=Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\nAccept-Language: fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7\r\nConnection: keep-alive\r\nContent-Type: application/x-www-form-urlencoded");
CString strTmp = "", strResult = "";
CHttpConnection* pHttpConnexion = NULL;
CHttpFile* pHttpFile = NULL;
try
{
//Creation de la connexion Http
pHttpConnexion = GetHttpConnection(strServerName, INTERNET_FLAG_RELOAD | INTERNET_FLAG_DONT_CACHE, nPort, NULL, NULL);
//Creation de la requete GET
pHttpFile = pHttpConnexion->OpenRequest(CHttpConnection::HTTP_VERB_POST, strObject, NULL, 1, NULL, NULL, INTERNET_FLAG_RELOAD | INTERNET_FLAG_DONT_CACHE);
//Envoi de la requéte
BOOL bRequestSend = pHttpFile->SendRequest(strHeaders, (LPVOID) (LPCTSTR) postData.c_str(), postData.length());
CString headers;headers.Empty();
DWORD dwRet;
pHttpFile->QueryInfo(HTTP_QUERY_RAW_HEADERS_CRLF,headers);
pHttpFile->QueryInfoStatusCode(dwRet);
CString data;
GetCookie(strServerName, "sess_id", data);
//Lecture du résultat
while ( pHttpFile->ReadString(strTmp))
{
strResult += strTmp;
}
//Fermeture de la requéte
pHttpFile->Close();
//Fermeture de la connexion
pHttpConnexion->Close();
//Suppression des objets
if (pHttpFile != NULL)
delete pHttpFile;
if (pHttpConnexion != NULL)
delete pHttpConnexion;
}
catch(CInternetException* exp)
{
exp->Delete();
//Fermeture de la requéte
if (pHttpFile != NULL)
{
pHttpFile->Close();
delete pHttpFile;
}
//Fermeture de la connexion
if (pHttpConnexion != NULL)
{
pHttpConnexion->Close();
delete pHttpConnexion;
}
throw CTSException("postRequest");
}
return strResult.GetString();
}
Thanks for helping!
when you construct your object and you call CInternetSession constructor, why the 3rd param is NULL? It should be something like PRE_CONFIG_INTERNET_ACCESS. You may need to use the proxy settings if you are behind a proxy.
check the content of strServerName, it may be invalid and GetHttpConnection fails because of that.
in your try, you GetHttpConnection and OpenRequest, but you don't check if the results aren't NULL. You only check later (too late) if they aren't NULL to delete them. You should check them after GetHttpConnection and OpenRequest, before using them. (But I guess the exception occurs during GetHttpConnection)
if the timeout occurs after 10sec, maybe it's because your timeout is too low (in your constructor).
there were some old reports that https may be a problem. But you didn't mentioned what was your request and what you were requesting.
in your request header, you are requesting different file formats (xml, html, png, etc...), but you are using a GetString and appending it to a string. If you are getting a binary data, it may not work. You should use a char[] buffer. Check this example.
after using your object ChttpConnexion, did you call .Close() on it?
In the end, I would recommend attaching a debugger and put a breakpoint in the catch to see where exactly the error occurs, or add some debug logs. This may help.

How to get multiple av_read_frame with FFmpeg

I want to get "2 signals" when I read an audio file. I know that I must use the FFmpeg function av_read_frame, but I have just that I call "1 signal". How can I have multiple signals to treat each signal in different way ?
My code is like that :
while (av_read_frame(pFormatCtx, packet) >= 0)
{
/* AVPacket == Audio */
if (packet->stream_index == audioStream)
{
/* Décodage des packets */
ret = avcodec_decode_audio4(pCodecCtx, pFrame, &got_picture, packet);
if (ret < 0)
{
fprintf(stderr, "%s\n", "Error in decoding audio frame");
return (-1);
}
if (got_picture > 0)
{
/* Convertissage de l'audio */
swr_convert(au_convert_ctx, &out_buffer, MAX_AUDIO_FRAME_SIZE, (const uint8_t **)pFrame->data, pFrame->nb_samples);
#if 1
/* Affichage des informations dans la console */
printf("Index : %5d\t Points : %lld\t Packet size : %d\n", index, packet->pts, packet->size);
#endif /* 1 */
#if OUTPUT_PCM
/* Fonction pour écrire dans le fichier */
fwrite(out_buffer, 1, out_buffer_size, pFile);
#endif /* OUTPUT_PCM */
/* Incrémentation */
index = index + 1;
}
#if USE_SDL
while (audio_len > 0)
SDL_Delay(1);
/* Attribution des valeurs avec les variables globales */
audio_chunk = (Uint8 *)out_buffer;
audio_len = out_buffer_size;
audio_pos = audio_chunk;
SDL_PauseAudio(0);
#endif /* USE_SDL */
}
/* Libérer la structure AVPacket */
av_free_packet(packet);
}

Server/Client TCP asynchronous (winsock) // FD_WRITE issue

I need your help because I have to make two console application in C++ : a client able to send as many string as possible to a server (in order to send coordinates). I succeeded to make a blocking socket but as I have to integrate it after in a development platform (3D VIA Virtools) which call my script at each frame, I have no other solution than using asynchronous sockets.
*My problem is that I can only send string once, and after I don't receive FD_WRITE anymore...*
This begin to drive me crazy so any help will be highly appreciated (I'm a beginner in programming), thanks in advance to everyone who will feel a little bit concerned by my problem
Here is my code,
Server
#include <winsock2.h>
#include <Windows.h>
#include <conio.h>
#pragma comment(lib, "ws2_32.lib")
#define SOCKET_ERRNO WSAGetLastError()
#define ADDRESS "127.0.0.1"
#define PORT 1234
static SOCKET ListenFirstFreePort()
{
struct sockaddr_in addr;
int len = sizeof(addr);
SOCKET hSocket;
// Create socket
hSocket = socket( PF_INET, SOCK_STREAM, 0 );
if( hSocket == INVALID_SOCKET )
{
printf( "socket() error %d\n", SOCKET_ERRNO );
exit(1);
}
// Connexion setting for local connexion
addr.sin_family = AF_INET ;
addr.sin_addr.s_addr = inet_addr(ADDRESS);
addr.sin_port = htons (PORT);
// bind socket
if ( bind( hSocket, (struct sockaddr *)&addr, sizeof(addr)) == SOCKET_ERROR )
{
printf( "bind() error %d\n", SOCKET_ERRNO );
exit(1);
}
// listen
if ( listen( hSocket, 100) == SOCKET_ERROR )
{
printf( "listen() error %d\n", SOCKET_ERRNO );
exit(1);
}
return hSocket;
}
void main()
{
WSADATA stack_info;
SOCKET ahSocket[2];
WSAEVENT ahEvents[2];
DWORD dwEvent;
WSANETWORKEVENTS NetworkEvents;
int rc;
// Initialize Winsock
WSAStartup(MAKEWORD(2,0), &stack_info) ;
// Create events
ahEvents[0] = WSACreateEvent();
ahEvents[1] = WSACreateEvent();
// Create listening socket
ahSocket[0] = ListenFirstFreePort();
rc = WSAEventSelect(ahSocket[0], ahEvents[0], FD_ACCEPT );
if( rc == SOCKET_ERROR )
{
printf( "WSAEventSelect() error %d\n", SOCKET_ERRNO );
exit(1);
}
while (TRUE)
{
// Waiting for so;ething to happen
// Basically we'll firstly receive the connexion of the client socket
// and then we'll be notificated when there will be some data to read
// look for events
dwEvent = WSAWaitForMultipleEvents( 2, ahEvents, FALSE, WSA_INFINITE, FALSE);
switch (dwEvent)
{
case WSA_WAIT_FAILED:
printf("WSAEventSelect: %d\n", WSAGetLastError());
break;
case WAIT_IO_COMPLETION:
case WSA_WAIT_TIMEOUT:
break;
default:
//if there is one dwEvent-WSA_WAIT_EVENT_0 has to be substracted so as to dwEvent correspond to the index of the concerned socket
dwEvent -= WSA_WAIT_EVENT_0;
// enumeration of the events on the socket[dwEvent]
if (SOCKET_ERROR == WSAEnumNetworkEvents(ahSocket[dwEvent], ahEvents[dwEvent], &NetworkEvents))
{
printf("WSAEnumNetworkEvent: %d lNetworkEvent %X\n",
WSAGetLastError(), NetworkEvents.lNetworkEvents);
NetworkEvents.lNetworkEvents = 0;
}
else
{
if (FD_CLOSE & NetworkEvents.lNetworkEvents)
{
printf( "FD_CLOSE ok (dwEvent=%d)\n", dwEvent );
printf( "press a key to exit\n" );
getch(); // require conio.h
WSACloseEvent( ahEvents[0] );
WSACloseEvent( ahEvents[1] );
exit(0);
}
if (FD_READ & NetworkEvents.lNetworkEvents)
{
char szBuffer[256]; int cbRecv;
// Only the second socket expect to receive data
printf( "FD_READ ok (dwEvent=%d)\n", dwEvent );
// read data
cbRecv = recv( ahSocket[dwEvent], szBuffer, sizeof(szBuffer) - 1, 0 );
if( cbRecv <= 0 )
{
printf( "recv() error %d\n", SOCKET_ERRNO );
exit(1);
}
// On ecrit ce paquet (On remet le 0 au cas ou le paquet
// ait ete coupe en 2 - je sais, ca n'arrivera jamais en local)
// we put the 0 in case it has been cut - unlikey to happen on local network
szBuffer[cbRecv] = 0;
// write data in console window
printf( "socket %d : '%s'\n", dwEvent, szBuffer );
}
}
if (FD_ACCEPT & NetworkEvents.lNetworkEvents)
{
struct sockaddr_in addrAccept;
int lenAccept;
lenAccept = sizeof( addrAccept );
// we should have dwEvent=0
printf( "accept ok (dwEvent=%d)\n", dwEvent );
// we create another socket to accept the connexion with the client socket
ahSocket[1] = accept(ahSocket[dwEvent], (struct sockaddr *)&addrAccept, &lenAccept);
// we want to be informed on when we'll be able read data from it
rc = WSAEventSelect(ahSocket[1], ahEvents[1], FD_READ|FD_CLOSE );
if( rc == SOCKET_ERROR )
{
printf( "WSAEventSelect() error %d\n", SOCKET_ERRNO );
exit(1);
}
}
}
}
}
Client
#include <winsock2.h>
#include <conio.h>
#include <time.h>
#pragma comment(lib, "ws2_32.lib")
#define SOCKET_ERRNO WSAGetLastError()
#define ADDRESS "127.0.0.1"
#define PORT 1234
SOCKET ConnectToPort()
{
struct sockaddr_in addr;
SOCKET hSocket;
u_long arg; int err;
// Create socket
hSocket = socket( PF_INET, SOCK_STREAM, 0 );
if( hSocket == INVALID_SOCKET )
{
printf( "socket() error %d\n", SOCKET_ERRNO );
exit(1);
}
// Connexion setting for local connexion
addr.sin_family = AF_INET ;
addr.sin_addr.s_addr = inet_addr(ADDRESS);
addr.sin_port = htons (PORT);
// Connect
if( connect( hSocket, (struct sockaddr *)&addr, sizeof(addr) ) == SOCKET_ERROR )
{
// As we are in non-blocking mode we'll always have the error
// WSAEWOULDBLOCK whichis actually not one
if( SOCKET_ERRNO != WSAEWOULDBLOCK )
{
printf( "connect() error (%d)\n", SOCKET_ERRNO );
exit(1);
}
}
return hSocket;
}
void main()
{
int initClockTime;
WSADATA stack_info;
SOCKET ahSocket[1];
WSAEVENT ahEvents[1];
DWORD dwEvent;
WSANETWORKEVENTS NetworkEvents;
int rc;
// Initialize Winsock
WSAStartup(MAKEWORD(2,0), &stack_info) ;
// Create event
ahEvents[0] = WSACreateEvent();
// Create and connect a socket on the server socket
ahSocket[0]= ConnectToPort();
// not sure if I have to use or not
/*u_long arg = 1;
ioctlsocket( ahSocket[0] , FIONBIO, &arg );*/
// the application wants to receive notification of a completed connection
rc = WSAEventSelect(ahSocket[0], ahEvents[0], FD_CONNECT );
if( rc == SOCKET_ERROR )
{
printf( "WSAEventSelect() error %d\n", SOCKET_ERRNO );
exit(1);
}
while (TRUE)
{
// look for events
dwEvent = WSAWaitForMultipleEvents( 1, ahEvents, FALSE, 1000, FALSE);
switch (dwEvent)
{
case WSA_WAIT_FAILED:
printf("WSAEventSelect: %d\n", WSAGetLastError());
break;
case WAIT_IO_COMPLETION:
case WSA_WAIT_TIMEOUT:
break;
default:
printf("while\n");
//if there is one dwEvent-WSA_WAIT_EVENT_0 has to be substracted so as to dwEvent correspond to the index of the concerned socket
dwEvent -= WSA_WAIT_EVENT_0;
// enumeration of the events on the socket[dwEvent]
if (SOCKET_ERROR == WSAEnumNetworkEvents(ahSocket[dwEvent], ahEvents[dwEvent], &NetworkEvents))
{
printf("WSAEnumNetworkEvent: %d lNetworkEvent %X\n", WSAGetLastError(), NetworkEvents.lNetworkEvents);
NetworkEvents.lNetworkEvents = 0;
}
else
{
if (FD_CONNECT & NetworkEvents.lNetworkEvents)
{
//connexion is OK
printf( "FD_CONNECT ok (dwEvent=%d)\n", dwEvent );
// now that we are connected we want to send data or be aware when the other socket is disconnected
rc = WSAEventSelect(ahSocket[dwEvent], ahEvents[dwEvent], FD_CLOSE | FD_WRITE );
if( rc == SOCKET_ERROR )
{
printf( "WSAEventSelect() error %d\n", SOCKET_ERRNO );
exit(1);
}
}
if (FD_CLOSE & NetworkEvents.lNetworkEvents)
{
printf( "FD_CLOSE ok (dwEvent=%d)\n", dwEvent );
printf( "press a key to exit\n" );
getch();
WSACloseEvent( ahEvents[0] );
exit(0);
}
if (FD_WRITE & NetworkEvents.lNetworkEvents)
{
char szBuffer[256]; int cbBuffer;
printf( "FD_WRITE ok (dwEvent=%d)\n", dwEvent );
// create string and return the size
cbBuffer = sprintf( szBuffer, "Coucou", dwEvent );
// send the string with 0 at the end
rc = send( ahSocket[dwEvent], szBuffer, cbBuffer + 1, 0 );
if (SOCKET_ERROR == rc)
{
printf("WSAEnumNetworkEvent: %d lNetworkEvent %X\n", WSAGetLastError(), NetworkEvents.lNetworkEvents);
}
// not sure if I have to use it
//WSAResetEvent(ahEvents[0]);
}
}
}
}
}
download .cpp files : https://www.dropbox.com/s/pjuipz7v4iwr5ea/Clientserver%20TCP.zip
You are not getting FD_WRITE notifications after the first one because you are not taking into account the following paragraph from the documentation:
The FD_WRITE network event is handled slightly differently. An
FD_WRITE network event is recorded when a socket is first connected
with a call to the connect, ConnectEx, WSAConnect, WSAConnectByList,
or WSAConnectByName function or when a socket is accepted with accept,
AcceptEx, or WSAAccept function and then after a send fails with
WSAEWOULDBLOCK and buffer space becomes available. Therefore, an
application can assume that sends are possible starting from the first
FD_WRITE network event setting and lasting until a send returns
WSAEWOULDBLOCK. After such a failure the application will find out
that sends are again possible when an FD_WRITE network event is
recorded and the associated event object is set.
After your first call to send(), the socket is still writable since its outbound buffer is not full. As long as you still have data to send, keep calling send() until it reports an WSAWOULDBLOCK error indicating the buffer is full. At that point, you have to keep track of your remaining data until you get an FD_WRITE notification indicating the socket is writable again so you can continue sending your remaining data from where you left off.
I would recommend to look at regular select() for non-blocking I/O first. Here's couple of links for you to get started:
Non-blocking I/O and select() (the link is broken)
Non-Blocking Sockets in TCP/IP

Get OU (Organizational Unit) name that a local computer belongs to using C++

I need to find out the name of the OU that the local computer (that is connected to the Active Directory) belongs to using WinAPI/C++. Any ideas?
In theory, this is fairly simple: connect to the server with ADsOpenObject, instantiate an IDirectorySearch and invoke its ExecuteSearch method, then use GetFirstRow and GetNextRow to walk through the result data (but for this query, you'll only expect one row).
In reality, however, all of this is COM -- so expect those half dozen (or so) function calls to be pretty much lost in at least a hundred lines of COM-cruftiness (and by the time the code is solid and robust, don't be surprised if it's closer to 1000 lines, most of which have no noticeable connection to Active Directory).
I should add that there are almost certainly other ways to do this -- as I recall, MS provides at least two or three different ways to access LDAP-type data. When I wrote some code for this, I initially tried to find which would be the cleanest, but gave up in frustration. There seemed to be no hope for cleanest -- at least at that time, I settled for "ugly but somewhat documented".
For a simple WINAPI (not COM) way to acces Active Directory in C or C++ see Lightweight Directory Access Protocol
void AfficheErreurLdap(char *fonction, ULONG rc);
/*
*
* Fonction d'entrée du programme
*
*/
void main(int argc, char* argv[])
{
LDAP *pSessionLdap; // Pointeur vers la session LDAP
char *pHote; // Pointeur vers la chaîne représentant le nom de l'hôte
char *pUtilisateur; // Pointeur vers la chaîne représentant l'utilisateur
char *pMotDePasse; // Pointeur vers la chaîne représentant le mot de passe
char *pRacineLdap; // Pointeur vers la racine Ldap
ULONG rc; // Récupération du code de retour des appels
LDAPMessage *pResultat; // Pointeur vers le message résultat de la réquête LDAP
LDAPMessage *pEntree; // Utilisée lors du parcours du résultat pour l'affichage
char *pDN; // Pointeur vers le DN d'une entrée du résultat
char *pAttribut; // Pointeur vers la chaîne représentant l'attribut
BerElement *pBer = NULL;// "curseur" interne à l'API LDAP pour le parcours des elts
char **pValeurs; // Valeurs de l'attribut lors de l'affichage du résultat
int i; // Indice pour la parcours des valeurs d'attribut
/* Analyse des Paramètres de lancement et affichage d’un message d’erreur si incorrect */
if (argc != 5)
{
fprintf(stderr,"Syntaxe :\n\tex_cldap_1 Hote Utilisateur MotDePasse RacineLdap\n");
exit (1);
}
/* Récupération des paramètres des lancement */
pHote = argv[1];
pUtilisateur = argv[2];
pMotDePasse = argv[3];
pRacineLdap = argv[4];
/* Ouverture de la session LDAP et récupération du handle de session */
pSessionLdap = ldap_open( pHote, 389); /* 389 est le numéro de port standard LDAP */
if ( pSessionLdap == NULL )
{
// En cas d'erreur : affichage du message d'erreur adéquat
perror( "ldap_open" );
exit( 2 );
}
printf("Ouverture de la session réalisée\n");
/* Authentification du client */
/* Pour l'exemple, l'authentification est faite en tant qu'anonyme */
rc = ldap_simple_bind_s(pSessionLdap, pUtilisateur, pMotDePasse);
if ( rc != LDAP_SUCCESS )
{
// Erreur lors de l'authentification, on termine après affichage d'un message
AfficheErreurLdap("ldap_simple_bind_s", rc);
exit( 3 );
}
printf("Authentification réalisée\n");
/* */
/* Recherche des données dans l'annuaire */
/* */
rc = ldap_search_s(pSessionLdap, // Session LDAP
pRacineLdap, // Base de la recherche
LDAP_SCOPE_SUBTREE, // Sccpe : LDAP_SCOPE_BASE, LDAP_SCOPE_ONELEVEL, LDAP_SCOPE_SUBTREE
"(objectClass=*)", // Filtre de recherche
NULL, // Attributs que l'on souhaite visualiser
0, // Indique si l'on souhaite uniquement les types (1) ou
// Les attributs et les valeurs (0)
&pResultat ) ; // Pointeur vers le résultat
if (rc != LDAP_SUCCESS )
{
// Erreur lors de la recherche, on termine après affichage du message d'erreur
AfficheErreurLdap("ldap_search_s", rc);
exit (4);
}
printf("Requête réalisée\n");
/* On va maintenant parcourir le résultat et afficher les couples */
/* attributs, valeurs */
pEntree = ldap_first_entry( pSessionLdap, pResultat );
while (pEntree != NULL)
{
// Récupération du DN, et affichage de celui-ci
pDN = ldap_get_dn( pSessionLdap, pEntree );
if ( pDN != NULL )
{
printf( "dn: %s\n", pDN );
// Libération de la mémoire allouée par l'API LDAP
ldap_memfree( pDN );
}
// Pour chaque attribut, on va lire le couple attribut, valeur
pAttribut = ldap_first_attribute( pSessionLdap, pEntree, &pBer );
while ( pAttribut != NULL)
{
// Récupération des valeurs associées à un attribut
pValeurs = ldap_get_values( pSessionLdap, pEntree, pAttribut);
if (pValeurs != NULL )
{
for ( i = 0; pValeurs[i] != NULL; i++ )
printf( "%s: %s\n", pAttribut, pValeurs[i]);
// Libération des valeurs lues
ldap_value_free( pValeurs );
}
// Libération de la mémoire utilisée par l'attribut
ldap_memfree( pAttribut );
// Lecture de l'attribut suivant
pAttribut = ldap_next_attribute( pSessionLdap, pEntree, pBer );
}
// Passage à la ligne dans l'affichage
printf( "\n\n" );
// Récupération de l'entrée suivante de l'annuaire
pEntree = ldap_next_entry( pSessionLdap, pEntree );
}
// Libération du message de résultat
ldap_msgfree( pResultat );
/* Fin de la session LDAP */
ldap_unbind( pSessionLdap );
}
/*
*
* Fonction permettant d'afficher les erreurs des opérations LDAP
*
*
*/
void AfficheErreurLdap(char *fonction, ULONG rc)
{
fprintf(stderr,"Erreur LDAP dans la fonction '%s', Code : %ld (0x%xld)\n", fonction, rc,rc);
}
///////////////IDirectorySearch///////////////////////////////////////////////////////////
CComPtr<IDirectorySearch> pDSSearch;
hr = ADsGetObject( L"LDAP://DC=forest,DC=internal",
IID_IDirectorySearch,
(void**) &pDSSearch );
if ( !SUCCEEDED(hr) )
{
return 0;
}
LPWSTR pszAttr[] = { L"description", L"Name", L"distinguishedname" };
ADS_SEARCH_HANDLE hSearch;
DWORD dwCount = 0;
ADS_SEARCH_COLUMN col;
DWORD dwAttrNameSize = sizeof(pszAttr)/sizeof(LPWSTR);
// Search for all objects with the 'cn' property TESTCOMP.
hr = pDSSearch->ExecuteSearch(L"(&(objectClass=computer)(cn=TESTCOMP))",pszAttr ,dwAttrNameSize,&hSearch );
LPWSTR pszColumn;
while( pDSSearch->GetNextRow( hSearch) != S_ADS_NOMORE_ROWS )
{
// Get the property.
hr = pDSSearch->GetColumn( hSearch, L"distinguishedname", &col );
// If this object supports this attribute, display it.
if ( SUCCEEDED(hr) )
{
if (col.dwADsType == ADSTYPE_CASE_IGNORE_STRING)
wprintf(L"The description property:%s\r\n", col.pADsValues->CaseIgnoreString);
pDSSearch->FreeColumn( &col );
}
else
puts("description property NOT available");
puts("------------------------------------------------");
dwCount++;
}
pDSSearch->CloseSearchHandle(hSearch);
///////////////IDirectorySearch///////////////////////////////////////////////////////////
In this search you'll get
(*((col).pADsValues)).DNString
"CN=TESTCOMP,OU=OUnit3,OU=OUnit,DC=forest,DC=internal"
So this is path to your TESTCOMP and I believe OUnit3 is what you want.