Test Foro de elhacker.net SMF 2.1

Programación => Programación C/C++ => Mensaje iniciado por: AlbertoBSD en 21 Septiembre 2016, 17:07 PM

Título: CreateThread o CreateProcess
Publicado por: AlbertoBSD en 21 Septiembre 2016, 17:07 PM
Estoy haciendo un servidor en C el tema es cual funcion debo elegir como la deberia de aplicar.

Tengo 2 versiones de mi servidor, una para sistemas Unix y otra para Windows.

En unix no hay problema solo hago un fork y asunto resuelto:

if(listen(ListenSocket, BACKLOG) == -1) {
perror("error: listen");


        return 1;
    }
while(entrar) {
pid = fork();
switch(pid) {
case 0:
//Codigo para el Hijo
break;
case -1:
//Error no fallo Fork
break;
default:
//Get the PID for Parent
break;
}
}


Pero no he encontrado una solucion para Windows, el servidor funciona bastante bien, el punto que en windows no es Multihilo aun, y tarda en responder ya que lo hace en orden secuencial.

He visto los siguientes enlaces y aun no doy con una solucion sencilla al tema

http://stackoverflow.com/questions/985281/what-is-the-closest-thing-windows-has-to-fork
http://stackoverflow.com/questions/14642496/any-simple-quick-way-to-fork-on-windows-ansi-c-beginthread-beginthreadex

Repito tengo 2 archivos distintos uno para Windows con winsock y el otro para Unix con Sockets estandar del sistema.

Saludos!
Título: Re: CreateThread o CreateProcess
Publicado por: HardForo en 21 Septiembre 2016, 17:41 PM
La facil es compilar con Cygwin :) te va a funcionar fork() como esperas   ;-)

Título: Re: CreateThread o CreateProcess
Publicado por: AlbertoBSD en 21 Septiembre 2016, 17:48 PM
Tengo Cygwin y funciona bien, el detalle que como voy a distribuir la aplicación, quiero que sea lo mas estándar posible (Acorde a cada sistema) y que dependa de la menor cantidad de recursos externos.

Saludos!

Título: Re: CreateThread o CreateProcess
Publicado por: ivancea96 en 21 Septiembre 2016, 17:53 PM
Yo lo haría con threads. De hecho, el de unix también lo haría con threads. Además, así no tendrías que hacer mucho cambio.
Título: Re: CreateThread o CreateProcess
Publicado por: AlbertoBSD en 21 Septiembre 2016, 18:04 PM
Si ya vi que lo que necesito es un thread nuevo lo cual seria lo mas parecido a fork aun que con ligeros cambios

Estoy validando este ejemplo de Windows:

https://msdn.microsoft.com/en-us/library/windows/desktop/ms682516(v=vs.85).aspx (https://msdn.microsoft.com/en-us/library/windows/desktop/ms682516(v=vs.85).aspx)

Código (cpp) [Seleccionar]
#include <windows.h>
#include <tchar.h>
#include <strsafe.h>

#define MAX_THREADS 3
#define BUF_SIZE 255

DWORD WINAPI MyThreadFunction( LPVOID lpParam );
void ErrorHandler(LPTSTR lpszFunction);

// Sample custom data structure for threads to use.
// This is passed by void pointer so it can be any data type
// that can be passed using a single void pointer (LPVOID).
typedef struct MyData {
   int val1;
   int val2;
} MYDATA, *PMYDATA;


int _tmain()
{
   PMYDATA pDataArray[MAX_THREADS];
   DWORD   dwThreadIdArray[MAX_THREADS];
   HANDLE  hThreadArray[MAX_THREADS];

   // Create MAX_THREADS worker threads.

   for( int i=0; i<MAX_THREADS; i++ )
   {
       // Allocate memory for thread data.

       pDataArray[i] = (PMYDATA) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
               sizeof(MYDATA));

       if( pDataArray[i] == NULL )
       {
          // If the array allocation fails, the system is out of memory
          // so there is no point in trying to print an error message.
          // Just terminate execution.
           ExitProcess(2);
       }

       // Generate unique data for each thread to work with.

       pDataArray[i]->val1 = i;
       pDataArray[i]->val2 = i+100;

       // Create the thread to begin execution on its own.

       hThreadArray[i] = CreateThread(
           NULL,                   // default security attributes
           0,                      // use default stack size  
           MyThreadFunction,       // thread function name
           pDataArray[i],          // argument to thread function
           0,                      // use default creation flags
           &dwThreadIdArray[i]);   // returns the thread identifier


       // Check the return value for success.
       // If CreateThread fails, terminate execution.
       // This will automatically clean up threads and memory.

       if (hThreadArray[i] == NULL)
       {
          ErrorHandler(TEXT("CreateThread"));
          ExitProcess(3);
       }
   } // End of main thread creation loop.

   // Wait until all threads have terminated.

   WaitForMultipleObjects(MAX_THREADS, hThreadArray, TRUE, INFINITE);

   // Close all thread handles and free memory allocations.

   for(int i=0; i<MAX_THREADS; i++)
   {
       CloseHandle(hThreadArray[i]);
       if(pDataArray[i] != NULL)
       {
           HeapFree(GetProcessHeap(), 0, pDataArray[i]);
           pDataArray[i] = NULL;    // Ensure address is not reused.
       }
   }

   return 0;
}


DWORD WINAPI MyThreadFunction( LPVOID lpParam )
{
   HANDLE hStdout;
   PMYDATA pDataArray;

   TCHAR msgBuf[BUF_SIZE];
   size_t cchStringSize;
   DWORD dwChars;

   // Make sure there is a console to receive output results.

   hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
   if( hStdout == INVALID_HANDLE_VALUE )
       return 1;

   // Cast the parameter to the correct data type.
   // The pointer is known to be valid because
   // it was checked for NULL before the thread was created.

   pDataArray = (PMYDATA)lpParam;

   // Print the parameter values using thread-safe functions.

   StringCchPrintf(msgBuf, BUF_SIZE, TEXT("Parameters = %d, %d\n"),
       pDataArray->val1, pDataArray->val2);
   StringCchLength(msgBuf, BUF_SIZE, &cchStringSize);
   WriteConsole(hStdout, msgBuf, (DWORD)cchStringSize, &dwChars, NULL);

   return 0;
}



void ErrorHandler(LPTSTR lpszFunction)
{
   // Retrieve the system error message for the last-error code.

   LPVOID lpMsgBuf;
   LPVOID lpDisplayBuf;
   DWORD dw = GetLastError();

   FormatMessage(
       FORMAT_MESSAGE_ALLOCATE_BUFFER |
       FORMAT_MESSAGE_FROM_SYSTEM |
       FORMAT_MESSAGE_IGNORE_INSERTS,
       NULL,
       dw,
       MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
       (LPTSTR) &lpMsgBuf,
       0, NULL );

   // Display the error message.

   lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
       (lstrlen((LPCTSTR) lpMsgBuf) + lstrlen((LPCTSTR) lpszFunction) + 40) * sizeof(TCHAR));
   StringCchPrintf((LPTSTR)lpDisplayBuf,
       LocalSize(lpDisplayBuf) / sizeof(TCHAR),
       TEXT("%s failed with error %d: %s"),
       lpszFunction, dw, lpMsgBuf);
   MessageBox(NULL, (LPCTSTR) lpDisplayBuf, TEXT("Error"), MB_OK);

   // Free error-handling buffer allocations.

   LocalFree(lpMsgBuf);
   LocalFree(lpDisplayBuf);
}


Aunque parece complicado veo que no esta dificil de implementar y ajustar a mi proyecto, lo que si tengo que hacer es una función nueva que seria el equivalente a lo que tengo dentro del switch incluso estoy dejando las 2 versiones con la misma cantidad de lineas y solo dejo huecos donde existe diferencia entre una version y la otra

Saludos!