CreateThread o CreateProcess

Iniciado por AlbertoBSD, 21 Septiembre 2016, 17:07 PM

0 Miembros y 1 Visitante están viendo este tema.

AlbertoBSD

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!
Donaciones
1Coffee1jV4gB5gaXfHgSHDz9xx9QSECVW

HardForo

La facil es compilar con Cygwin :) te va a funcionar fork() como esperas   ;-)

HardForo:  foro de Hardware y programación

Se buscan Mods y colaboradores *

AlbertoBSD

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!

Donaciones
1Coffee1jV4gB5gaXfHgSHDz9xx9QSECVW

ivancea96

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.

AlbertoBSD

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

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!
Donaciones
1Coffee1jV4gB5gaXfHgSHDz9xx9QSECVW