elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Usando Git para manipular el directorio de trabajo, el índice y commits (segunda parte)


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderadores: Eternal Idol, Littlehorse, K-YreX)
| | |-+  [Sockets] Conexiones múltiples de clientes a servidor.
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: [Sockets] Conexiones múltiples de clientes a servidor.  (Leído 5,245 veces)
Zodiak98

Desconectado Desconectado

Mensajes: 120


Ver Perfil
[Sockets] Conexiones múltiples de clientes a servidor.
« en: 22 Enero 2016, 23:48 pm »

Verán, estoy aprendiendo sobre sockets y hasta ahora todo bien. El problema es que sólo puedo manejar una conexión a la vez, ¿cómo podría manejar conexiones múltiples? Leí un tema que se logra a través de un Thread, pero estoy un poco confundido.

Estos son los códigos que llevo hasta ahora:

Servidor:
Código
  1. #ifndef WIN32_LEAN_AND_MEAN
  2. #define WIN32_LEAN_AND_MEAN
  3. #endif
  4.  
  5. #include <windows.h>
  6. #include <WinSock2.h>
  7. #include <WS2tcpip.h>
  8. #include <IPHlpApi.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11.  
  12. #pragma comment(lib, "Ws2_32.lib")
  13.  
  14. #define DEFAULT_PORT "27016"
  15. #define DEFAULT_BUFLEN 516
  16.  
  17. int main() {
  18. WSADATA wsaData;
  19. int iResult;
  20.  
  21. char recvbuf[DEFAULT_BUFLEN];
  22. int recvbuflen = DEFAULT_BUFLEN;
  23. int recvBytes;
  24.  
  25. iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
  26. if (iResult != 0) {
  27. printf("WSAStartup failed with error: %d\n", iResult);
  28. return 1;
  29. }
  30.  
  31. struct addrinfo *result = NULL,
  32. hints;
  33.  
  34. ZeroMemory(&hints, sizeof(hints));
  35. hints.ai_family = AF_INET;
  36. hints.ai_socktype = SOCK_STREAM;
  37. hints.ai_protocol = IPPROTO_TCP;
  38. hints.ai_flags = AI_PASSIVE;
  39.  
  40. iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
  41. if (iResult != 0) {
  42. printf("getaddrinfo error: %d\n", iResult);
  43. WSACleanup();
  44. return 1;
  45. }
  46.  
  47. SOCKET ListenSocket = INVALID_SOCKET;
  48.  
  49. ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
  50.  
  51. if (ListenSocket == INVALID_SOCKET) {
  52. printf("Error at socket(): %ld\n", WSAGetLastError());
  53. freeaddrinfo(result);
  54. WSACleanup();
  55. return 1;
  56. }
  57.  
  58. iResult = bind(ListenSocket, result->ai_addr, result->ai_addrlen);
  59. if (iResult == SOCKET_ERROR) {
  60. printf("Error at bind: %d\n", iResult);
  61. freeaddrinfo(result);
  62. closesocket(ListenSocket);
  63. WSACleanup();
  64. return 1;
  65. }
  66.  
  67. freeaddrinfo(result);
  68.  
  69. if (listen(ListenSocket, SOMAXCONN) == SOCKET_ERROR) {
  70. printf("Listen failed with: %ld\n", WSAGetLastError());
  71. closesocket(ListenSocket);
  72. WSACleanup();
  73. return 1;
  74. }
  75.  
  76. SOCKET ClientSocket = INVALID_SOCKET;
  77.  
  78. ClientSocket = accept(ListenSocket, NULL, NULL);
  79. if (ClientSocket == INVALID_SOCKET) {
  80. printf("accept failed with error: %d\n", WSAGetLastError());
  81. closesocket(ListenSocket);
  82. WSACleanup();
  83. return 1;
  84. }
  85.  
  86. printf("A CONNECTION HAS BEEN FOUND!!\n");
  87.  
  88. iResult = shutdown(ClientSocket, SD_SEND);
  89. if (iResult == SOCKET_ERROR) {
  90. printf("shutdown failed with error: %d\n", iResult);
  91. closesocket(ClientSocket);
  92. WSACleanup();
  93. return 1;
  94. }
  95.  
  96. do {
  97. recvBytes = recv(ClientSocket, recvbuf, recvbuflen, 0);
  98. if (recvBytes > 0) {
  99. printf("Client >> ");
  100. for (int i = 0; i < recvBytes; ++i) {
  101. printf("%c", recvbuf[i]);
  102. }
  103. //printf("Bytes received: %d\n\n", recvBytes);
  104. }
  105. else if (recvBytes == 0) {
  106. printf("Connection closing...\n");
  107. }
  108. else {
  109. printf("recv failed: %d\n", WSAGetLastError());
  110. closesocket(ClientSocket);
  111. WSACleanup();
  112. return 1;
  113. }
  114. } while (recvBytes > 0);
  115.  
  116. closesocket(ClientSocket);
  117. WSACleanup();
  118.  
  119. system("pause>nul");
  120.  
  121. return 0;
  122. }
  123.  

Cliente:
Código
  1. #ifndef WIN32_LEAN_AND_MEAN
  2. #define WIN32_LEAN_AND_MEAN
  3. #endif
  4.  
  5. #include <windows.h>
  6. #include <WinSock2.h>
  7. #include <WS2tcpip.h>
  8. #include <IPHlpApi.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11.  
  12. #pragma comment(lib, "Ws2_32.lib")
  13.  
  14. #define DEFAULT_PORT "27016"
  15. #define DEFAULT_BUFLEN 516
  16.  
  17. int main() {
  18. WSADATA wsaData;
  19. int iResult;
  20.  
  21. char sendbuf[DEFAULT_BUFLEN];
  22. int iSendResult;
  23.  
  24. iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
  25. if (iResult != 0) {
  26. printf("WSAStartup failed with error: %d\n", iResult);
  27. return 1;
  28. }
  29.  
  30. struct addrinfo *result = NULL,
  31. *ptr = NULL,
  32. hints;
  33.  
  34. ZeroMemory(&hints, sizeof(hints));
  35. hints.ai_family = AF_UNSPEC;
  36. hints.ai_socktype = SOCK_STREAM;
  37. hints.ai_protocol = IPPROTO_TCP;
  38.  
  39. iResult = getaddrinfo("127.0.0.1", DEFAULT_PORT, &hints, &result);
  40. if (iResult != 0) {
  41. printf("getaddrinfo failed with error: %d/n", iResult);
  42. WSACleanup();
  43. return 1;
  44. }
  45.  
  46. SOCKET ConnectSocket = INVALID_SOCKET;
  47.  
  48. ptr = result;
  49.  
  50. ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
  51.  
  52. if (ConnectSocket == INVALID_SOCKET) {
  53. printf("Error at socket(): %ld\n", WSAGetLastError());
  54. freeaddrinfo(result);
  55. WSACleanup();
  56. return 1;
  57. }
  58.  
  59. iResult = connect(ConnectSocket, ptr->ai_addr, ptr->ai_addrlen);
  60. if (iResult == SOCKET_ERROR) {
  61. closesocket(ConnectSocket);
  62. ConnectSocket = INVALID_SOCKET;
  63. }
  64.  
  65. freeaddrinfo(result);
  66.  
  67. if (ConnectSocket == INVALID_SOCKET) {
  68. printf("Unable to connect to server!\n");
  69. WSACleanup();
  70. return 1;
  71. }
  72.  
  73. do {
  74. printf("Send a message to the server: ");
  75. fgets(sendbuf, DEFAULT_BUFLEN, stdin);
  76.  
  77. iSendResult = send(ConnectSocket, sendbuf, (int)strlen(sendbuf), 0);
  78. if (iSendResult == SOCKET_ERROR) {
  79. printf("send failed: %d\n", WSAGetLastError());
  80. closesocket(ConnectSocket);
  81. WSACleanup();
  82. return 1;
  83. }
  84. //printf("Bytes sent: %d\n\n", iSendResult);
  85. } while (iSendResult > 0);
  86.  
  87. iResult = shutdown(ConnectSocket, SD_SEND);
  88. if (iResult == SOCKET_ERROR) {
  89. printf("shutdown failed: %d\n", iResult);
  90. closesocket(ConnectSocket);
  91. WSACleanup();
  92. return 1;
  93. }
  94.  
  95. closesocket(ConnectSocket);
  96. WSACleanup();
  97.  
  98. system("pause>nul");
  99.  
  100. return 0;
  101. }
  102.  

Estoy trabajando en Visual Studio Community 2015.


En línea

sodark

Desconectado Desconectado

Mensajes: 81


Ver Perfil WWW
Re: [Sockets] Conexiones múltiples de clientes a servidor.
« Respuesta #1 en: 22 Enero 2016, 23:59 pm »

No me he leido tu codigo pero te comento lo que se suele hacer en todos los lenguajes

- Inicias un servidor que escuche un puerto.
- Esperas a recibir un Accept (esto te devolvera un filedescriptor en C que sera el socket abierto, o un Socket en Java)
- Pasas ese filedescriptor / socket a un thread, donde sera atendido

Para que te hagas una idea en C tengo algo asi

Código
  1.  
  2. while( 1 == 1 ) {
  3. client_socket = accept(server_socket, (struct sockaddr *) &client, &client_length);
  4. if (client_socket < 0) {
  5. close(server_socket);
  6. close(client_socket);
  7. } else {
  8. run_dozer_thread(client_socket);
  9. }
  10. }
  11.  

Donde run dozer thread

Código
  1. /**********************************************
  2. * @Nombre: run_dozer_thread
  3. * @Def: Funcion encargada lanzar el Thread del Dozer
  4. * @Arg: int socket_cliente
  5. * @Ret:   void
  6. **********************************************/
  7. void run_dozer_thread(int client_socket) {
  8. pthread_t thread_dozer_id;
  9. pthread_create(&thread_dozer_id, NULL, thread_manage_dozer, (void *)client_socket);
  10. }
  11.  


En línea

mester

Desconectado Desconectado

Mensajes: 219


https://www.youtube.com/watch?v=IlY9C6pzxKc


Ver Perfil WWW
Re: [Sockets] Conexiones múltiples de clientes a servidor.
« Respuesta #2 en: 23 Enero 2016, 13:16 pm »

Crear un thread para cada cliente es una faena y si tienes un ordenador poco potente es ineficiente. Yo te recomendaría usar la función select(); https://msdn.microsoft.com/en-us/library/windows/desktop/ms740141%28v=vs.85%29.aspx
Con esta función sabes si ha habido alguna novedad o notificación en un socket, es decir, si se ha recibido algo. Los sockets se almacenan en un array en la estructura https://msdn.microsoft.com/en-us/library/windows/desktop/ms737873%28v=vs.85%29.aspx
El programa seguiría el hilo logico siguiente:
Código:
Si select() recibe una notificación del SOCKET a la escucha
  Acepta conexión del nuevo cliente
  Si el cliente se ha conectado correctamente añade el socket a fd_set
Si no, si recibe una notificación del algun socket que no sea el de escucha
  Lee el descriptor que ha enviado el mensaje
  Envia el mismo mensaje al resto de sockets excepto al que lo envía y al socket servidor
Mas o menos ese sería el esquema que debe seguir el bucle.
En línea

Justicia es dar a cada uno lo que se merece
kondrag_X1

Desconectado Desconectado

Mensajes: 157


Ver Perfil
Re: [Sockets] Conexiones múltiples de clientes a servidor.
« Respuesta #3 en: 23 Enero 2016, 13:24 pm »

http://www.cs.dartmouth.edu/~campbell/cs50/socketprogramming.html en el link explica lo básico de los socket como puedes manejar peticiones esta muy bien con sus diagramas.

Pero si quieres controlar varios socket a la vez yo creo que tendrás que usar select
http://www.chuidiang.com/clinux/sockets/socketselect.php
En línea

sodark

Desconectado Desconectado

Mensajes: 81


Ver Perfil WWW
Re: [Sockets] Conexiones múltiples de clientes a servidor.
« Respuesta #4 en: 23 Enero 2016, 21:15 pm »

Ya y si tengo que realizar operaciones al mismo tiempo porque no paran de enviar peticiones? (Obviamente no me refiero para este ejercicio)
En línea

mester

Desconectado Desconectado

Mensajes: 219


https://www.youtube.com/watch?v=IlY9C6pzxKc


Ver Perfil WWW
Re: [Sockets] Conexiones múltiples de clientes a servidor.
« Respuesta #5 en: 24 Enero 2016, 18:03 pm »

Ya y si tengo que realizar operaciones al mismo tiempo porque no paran de enviar peticiones? (Obviamente no me refiero para este ejercicio)


Puedes usar threads o crear procesos hijos con fork(); sino puedes hacer bien el programa con varias condiciones y tal. Pero si quieres hacer las cosas así, pues threads.
En línea

Justicia es dar a cada uno lo que se merece
sodark

Desconectado Desconectado

Mensajes: 81


Ver Perfil WWW
Re: [Sockets] Conexiones múltiples de clientes a servidor.
« Respuesta #6 en: 25 Enero 2016, 00:42 am »

Puedes usar threads o crear procesos hijos con fork(); sino puedes hacer bien el programa con varias condiciones y tal. Pero si quieres hacer las cosas así, pues threads.

La verdad es que a fork no le veo sentido.

- No comparten memoria (para comunicarse se han de crear las pipes y una rutina de gestion de comunicacion)
- Se duplica todo el espacio de memoria, toda variable, por lo que si se conectan 10 clientes tengo 10 x consumo de memoria.

Con los threads te ahorras la rutina de gestion de comunicación entre padre e hijo, tan solo debes poner unos mutex en las zonas criticas. El gasto de memoria es el "mismo" (obviamente un par de variables mas pero no todo duplicado).

Lo que me parecería interesante es que explicaras como hacer un multiservidor que atienda las peticiones de multiples clientes (llegando a la vez y realizando operaciones que puedan llevar mas de 1 segundo en dar resultado al cliente) sin tener que hacer esperar a los clientes ya que es un solo hilo de ejecució.

Mas que nada porque a mi no se me ocurre y así aprendería algo nuevo :)

En línea

Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
Duda cliente-servidor, multiples conexiones, administrador de conexiones
Programación Visual Basic
-Xenon- 8 5,234 Último mensaje 14 Enero 2006, 14:44 pm
por -Xenon-
SERVIDOR CON MULTIPLES CLIENTES
Java
lexoazul 2 8,610 Último mensaje 23 Octubre 2009, 05:39 am
por Leyer
Permitir múltiples conexiones a un servidor Winsock
Programación Visual Basic
Brian1511 2 2,366 Último mensaje 17 Diciembre 2012, 17:48 pm
por Brian1511
Sockets C#: Multiples Conexiones
Programación General
9ttnix 0 2,597 Último mensaje 29 Mayo 2013, 23:11 pm
por 9ttnix
Abrir multiples conexiones Sockets C « 1 2 »
Programación C/C++
mester 13 6,598 Último mensaje 11 Noviembre 2015, 19:21 pm
por ivancea96
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines