 |
|
Page 1 sur 1
|
Voir le sujet précédent :: Voir le sujet suivant |
Auteur |
Message |
Posté le: Mar Mar 15, 2011 9:57 am Sujet du message: [Winsock]Thread Recv/send non fonctionnel |
|
|
{RISEN}
Projets
Inscrit le: 28 Oct 2010
Messages: 14
|
Bonjour Ă tous !
Me voilà encore une fois car je me suis lancé dans les sockets... Mais bien que l'envie soit la, je suis rebuté encore une fois par de détails :
1 - La thread qui s'occupe d'envoyer ou recevoir ne reçois ni envois rien...
2 - Si je met un recv/send après acceptation d'un nouveau client, cela fonctionne mais qu'une seule fois (alors que côté client, une boucle se charge d'envoyer tout le temps les infos)
3 - Je n'ai pas encore compris comment envoyez et recevoir sur la mĂŞme application... Une explication serais la bienvenue
Je sais que le code est dégueulasse et je m'en excuse... C'est un serveur/client de test dans le but de bien tout comprendre avant de me lancer dans un soft plus propre et plus générique... Mais pour ça il me faut bien comprendre tout son fonctionnement.
Un GROS merci à ceux qui pourrons répondre à mes questions !!
 |
 |
#define MAX_CLIENTS 10
#include <fstream>
using namespace std;
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <winsock.h>
#pragma comment(lib,"ws2_32.lib")
#pragma comment(lib,"pthreadVC2.lib")
#include <pthread.h>
#if defined (WIN32)
#include <winsock2.h>
typedef int socklen_t;
#elif defined (linux)
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#define closesocket(s) close (s)
typedef int SOCKET;
typedef struct sockaddr_in SOCKADDR_IN;
typedef struct sockaddr SOCKADDR;
#endif
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#define PORT 55555
typedef struct ClientInfos
{
int ID;
char User[32];
char Password[32];
char Name[200];
int IsRegister;
int Packet;
int Alive;
int sayChat;
char Chat[512];
int nbrClients;
int UseRefID;
}ClientInfos;
ClientInfos ClientInfo[30];
typedef struct Client
{
SOCKET ClientSocket;
};
Client Client[MAX_CLIENTS];
SOCKET csock;
SOCKET sock;
int client=0;
pthread_t ThreadRecvAndSend;
void *Sync_Client(void *data);
int main(void)
{
#if defined (WIN32)
WSADATA WSAData;
int erreur = WSAStartup(MAKEWORD(2,2), &WSAData);
#else
int erreur = 0;
#endif
SOCKADDR_IN sin;
int recsize = sizeof sin;
int sock_err;
if(!erreur)
{
sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock != INVALID_SOCKET)
{
printf("La socket %d est maintenant ouverte en mode TCP/IP\n", sock);
sin.sin_addr.s_addr = htonl(INADDR_ANY);
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
sock_err = bind(sock, (SOCKADDR*) &sin, recsize);
if(sock_err != SOCKET_ERROR)
{
sock_err = listen(sock, 5);
printf("Listage du port %d...\n", PORT);
if(sock_err != SOCKET_ERROR)
{
fd_set readfs;
while(1)
{
FD_ZERO(&readfs);
FD_SET(sock, &readfs);
if(select(sock + 1, &readfs, NULL, NULL, NULL) < 0)
{
perror("select()");
exit(errno);
}
if(FD_ISSET(sock, &readfs))
{
SOCKADDR_IN csin;
int crecsize = sizeof csin;
SOCKET csock = accept(sock, (SOCKADDR *) &csin, &crecsize);
printf("Un client s'est connecte\n");
pthread_create(&ThreadRecvAndSend, NULL, Sync_Client, NULL);
client++;
}
}
}
}
}
}
#if defined (WIN32)
WSACleanup();
#endif
return EXIT_SUCCESS;
}
void *Sync_Client(void *data)
{
bool Connected = 1;
while(Connected)
{
if(recv(csock, reinterpret_cast<char*>(&ClientInfo), sizeof(ClientInfo), 0) != SOCKET_ERROR)
{
printf("%s test\n", ClientInfo[1].User);
}
else if (send(csock, reinterpret_cast<char*>(&ClientInfo), sizeof(ClientInfo), 0) != SOCKET_ERROR)
{
printf("%s test\n", ClientInfo[1].User);
}
else Connected = false;
}
} |
|
|
|
|
 |
Posté le: Mar Mar 15, 2011 12:45 pm Sujet du message: |
|
|
TorTukiTu
Site Admin

Inscrit le: 07 Fév 2008
Messages: 1960
Localisation: Devant son pc durant la redaction de ce message |
Dieu du ciel, ce code est Ă vomir...
C'est du C ou du CPP ?
Je n'insiterai pas sur les conneries et autres mochetées diverses et variées de ce code.
Le problème vient du fait que ton thread ne partage pas les mêmes variables que le processus père, et même si c'était le cas, tu vois bien qu'à chaque fois qu'un client se connecte, tu réinitialise ta variable csock.
La solution la plus simple est de passer ta variable csock comme argument de pthread_create.
Ce qui donne le code suivant:
 |
 |
#define MAX_CLIENTS 10
//using namespace std;
#include <stdio.h>
#include <string.h>
#pragma comment(lib,"ws2_32.lib")
#pragma comment(lib,"pthreadVC2.lib")
#include <pthread.h>
#if defined (WIN32)
#include <winsock2.h>
typedef int socklen_t;
#elif defined (linux)
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#define closesocket(s) close (s)
typedef int SOCKET;
typedef struct sockaddr_in SOCKADDR_IN;
typedef struct sockaddr SOCKADDR;
#endif
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#define PORT 55555
typedef struct ClientInfos
{
int ID;
char User[32];
char Password[32];
char Name[200];
int IsRegister;
int Packet;
int Alive;
int sayChat;
char Chat[512];
int nbrClients;
int UseRefID;
}ClientInfos;
typedef struct Client
{
SOCKET ClientSocket;
};
Client Client[MAX_CLIENTS];
ClientInfos ClientInfo[30];
SOCKET csock;
SOCKET sock;
int client=0;
pthread_t ThreadRecvAndSend;
void *Sync_Client(void *data);
int main(void)
{
#if defined (WIN32)
WSADATA WSAData;
int erreur = WSAStartup(MAKEWORD(2,2), &WSAData);
#else
int erreur = 0;
#endif
SOCKADDR_IN sin;
int recsize = sizeof sin;
int sock_err;
if(!erreur)
{
sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock != INVALID_SOCKET)
{
printf("La socket %d est maintenant ouverte en mode TCP/IP\n", sock);
sin.sin_addr.s_addr = htonl(INADDR_ANY);
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
sock_err = bind(sock, (SOCKADDR*) &sin, recsize);
if(sock_err != SOCKET_ERROR)
{
sock_err = listen(sock, 5);
printf("Listage du port %d...\n", PORT);
if(sock_err != SOCKET_ERROR)
{
fd_set readfs;
while(1)
{
FD_ZERO(&readfs);
FD_SET(sock, &readfs);
if(select(sock + 1, &readfs, NULL, NULL, NULL) < 0)
{
perror("select()");
exit(errno);
}
if(FD_ISSET(sock, &readfs))
{
SOCKADDR_IN csin;
int crecsize = sizeof csin;
SOCKET csock = accept(sock, (SOCKADDR *)&csin, (socklen_t *)&crecsize);
printf("Un client s'est connecte\n");
pthread_create(&ThreadRecvAndSend, NULL, Sync_Client, (void *)csock);
client++;
}
}
}
}
}
}
#if defined (WIN32)
WSACleanup();
#endif
return EXIT_SUCCESS;
}
void *Sync_Client(void *data)
{
SOCKET csock = (SOCKET)data;
bool Connected = 1;
char * buffer[1024];
while(Connected)
{
if(recv(csock, buffer, sizeof(ClientInfo), 0) != SOCKET_ERROR)
{
// ATTENTION ICI %s Affiche ta structure jusqu'à ce que \0 (fin de chaine) soit rencontrée. Si \0 n'est pas dans la chaine envoyée par le client, le printf continuera a afficher la structure.
// Tu dois donc t'assurer ici que seul les 32 chars de User seront affichés.
printf("%s test\n", (( struct ClientInfos *)buffer)->User);
}
else if (send(csock, reinterpret_cast<char*>(&ClientInfo), sizeof(ClientInfo), 0) != SOCKET_ERROR)
{
printf("%s test\n", ClientInfo[1].User);
}
else Connected = false;
}
} |
 |
 |
3 - Je n'ai pas encore compris comment envoyez et recevoir sur la mĂŞme application... Une explication serais la bienvenue |
Si tu veux faire communiquer des processus et des threads entre eux, il faut que tu te rensigne sur ce que l'on appelle les IPC. [Inter Process Communication]
Envoyer un message à travers une socket vers une machine extérieure ou localement revient au même d'un point de vue programmaton. Pour communiquer avec toi-même, il faut que tu utilises localhost, soit l'ip (définie par standard) 127.0.0.1
Ensuite, il faut bien que tu comprennes ce qu'est un Thread, un Zombie, et d'une façon générale la gestion des processus par la machine. Il existe de très nombreux tutos sur le net pour ça.
Pour finir, RESPECTE LES CONVENTIONS. Si tu fais du C, compile avec gcc -Wall -pedantic -ansii
Si tu fais du C++, alors tu t'y tiens et tu fais de l'objet. Mais mixes pas les choses d'une façon aussi immonde. Je pense que ça montre à quel point tu es désordonné dans ta tête sur ce coup là ... Si je peux te conseiller quelquechose, mets les choses au clair avec les normes et les conventions et recommence tout.
(Pour tester ton application, tu peux utiliser telnet pour simuler ton client ou netcat pour le coté serveur.)
La tortue du 974. |
|
|
|
 |
Posté le: Mer Mar 16, 2011 1:45 pm Sujet du message: |
|
|
{RISEN}
Projets
Inscrit le: 28 Oct 2010
Messages: 14
|
 |
 |
Ensuite, il faut bien que tu comprennes ce qu'est un Thread, un Zombie, et d'une façon générale la gestion des processus par la machine. Il existe de très nombreux tutos sur le net pour ça. |
C'est bien une fonction qui preux prendre x paramètres + initialisation de la thread, qui à la particularité d'être lue (voir répétée si dans une boucle ?-) en même temps que le programme sans bloquer celui-ci ?
 |
 |
Pour finir, RESPECTE LES CONVENTIONS. Si tu fais du C, compile avec gcc -Wall -pedantic -ansii |
Comme dis plus haut, j'ai pour habitude quand j'apprend une lib de faire un programme "chantier" me permettant de tester à l'arrache l'ensemble de possibilités. Mais j'admet que oser poster un code aussi dégueulasse... Étais carrément stupide
 |
 |
Si tu veux faire communiquer des processus et des threads entre eux, il faut que tu te rensigne sur ce que l'on appelle les IPC. [Inter Process Communication] |
En fait je ne pense que j'ai j'ai besoins de faire cela (dans un premier temps en tous cas). Pour faire simple, j'ai besoins que le serveur puisse récupérer en recv :
 |
 |
ClientInfo //Qui est une structure globale contenant les info DU client |
puis :
 |
 |
OtherClientInfo[ClientInfo.ID]. ID //Chaque tableau du OtherClientInfo étant un client |
Et enfin envoyer la structure globale OtherClientInfo à tous les clients... J'ai donc retenté l'experience :
 |
 |
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include "memory.h"
#define SERVER_VERSION "0.4"
#ifdef WIN32
#include <winsock2.h>
#pragma comment(lib, "wsock32.lib")
#pragma comment(lib, "pthreadVC2.lib")
#else
#include <sys/socket.h>
#include <sys/types.h>
#include <resolv.h>
#include <netdb.h>
#define SOCKET int
#endif
#include <stdio.h>
#include <stdlib.h>
typedef struct ClientInfos
{
int ID;
char User[32];
char Password[32];
char Name[32];
int IsRegister;
int Packet;
int Alive;
int sayChat;
char Chat[512];
int nbrClients;
int UseRefID;
}ClientInfos;
ClientInfos ClientInfo;
typedef struct OtherClientInfo
{
int ID;
char User[32];
char Password[32];
char Name[32];
int IsRegister;
int Packet;
int Alive;
int sayChat;
char Chat[512];
int nbrClients;
int UseRefID;
}OtherClientInfo;
OtherClientInfo OtherClientInfos[30];
int CheckHandlerPacket()
{
int id = ClientInfo.ID;
char user[32];
char password[32];
char name[32];
char chat[512];
strcpy(user, ClientInfo.User);
strcpy(OtherClientInfos[id].User, user);
strcpy(name, ClientInfo.Name);
strcpy(OtherClientInfos[id].Name, name);
strcpy(password, ClientInfo.Password);
strcpy(OtherClientInfos[id].Password, password);
strcpy(chat, ClientInfo.Chat);
strcpy(OtherClientInfos[id].Chat, chat);
OtherClientInfos[id].ID = id;
OtherClientInfos[id].IsRegister = ClientInfo.IsRegister;
OtherClientInfos[id].Packet = ClientInfo.Packet;
OtherClientInfos[id].Alive = ClientInfo.Alive;
OtherClientInfos[id].sayChat = ClientInfo.sayChat;
OtherClientInfos[id].UseRefID = ClientInfo.UseRefID;
if(ClientInfo.Packet != 0)
{
switch(ClientInfo.Packet)
{
case 1: //Try yo login...
printf("%s(%d) is login to the gameserver ...\n", ClientInfo.User, ClientInfo.ID);
break;
case 2://Using object sending to the other clients
printf("%s(%d) use object with this refID : %x ...\n", ClientInfo.User, ClientInfo.ID, ClientInfo.UseRefID);
break;
case 3://Sending chat text
printf("%s say : %s\n", ClientInfo.User, ClientInfo.Chat);
break;
default:
printf("%s send bad packet(%d)", ClientInfo.User, ClientInfo.Packet);
break;
}
}else return 0;
}
void * memoryAlloc(size_t sizeOfBlock)
{
void * ptr = NULL;
ptr = malloc(sizeOfBlock);
if(ptr == NULL)
{
fprintf(stderr,"Allocation impossible \n");
exit(EXIT_FAILURE);
}
return ptr;
}
void memoryFree(void * ptr)
{
free(ptr);
ptr = NULL;
}
typedef struct{
SOCKET sock;
SOCKADDR_IN data;
pthread_t clientThread;
}socket_t;
int clientNumber = 0;
void * clientManager(socket_t * client)
{
socket_t * mclient = client;
char * buffer = NULL;
char * clientBuffer = NULL;
int i=1;
pthread_detach(mclient->clientThread);
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
buffer = memoryAlloc(sizeof(char) * 64);
sprintf(buffer, "%s", inet_ntoa(mclient->data.sin_addr)); // on récupère l'adresse du client
printf("Client : %s - %i client(s) en ligne\n", buffer, clientNumber);
clientBuffer = memoryAlloc(sizeof(char) * 1024);
while(i)
{
recv(mclient->sock, &ClientInfo, sizeof(ClientInfo), 0);
int id = ClientInfo.ID;
if (ClientInfo.Packet != 0)
CheckHandlerPacket();
int try = send(mclient->sock, &OtherClientInfos, sizeof(OtherClientInfos), 0);
OtherClientInfos[id].sayChat = 0;
if(try == SOCKET_ERROR)
{
memoryFree(clientBuffer);
shutdown(mclient->sock, 2);
clientNumber--;
printf("deconnection de %s - %i client(s) en ligne\n", buffer, clientNumber);
memoryFree(mclient);
memoryFree(buffer);
pthread_exit(0);
}
}
return 0;
}
int main(int count, char **args)
{
#ifdef WIN32
WSADATA wsaData;
#endif
socket_t server;
socket_t * client = NULL;
int clientDataSize = sizeof(SOCKADDR_IN);
#ifdef WIN32
if (WSAStartup(MAKEWORD(2, 2), &wsaData))
exit(EXIT_FAILURE);
printf("Experimental Server v. %s\n MS Windows version\n", SERVER_VERSION);
printf(" * Winsock v%i.%i\n", LOBYTE(wsaData.wVersion), HIBYTE(wsaData.wVersion));
#else
printf("Experimental Server v. 0.2\n Unix version");
#endif
server.sock = socket(PF_INET, SOCK_STREAM, 0);
server.data.sin_addr.s_addr = INADDR_ANY;
server.data.sin_family = AF_INET;
server.data.sin_port = htons(55555);
bind(server.sock, (SOCKADDR *)&(server.data), sizeof(server.data));
listen(server.sock, 0);
while(1)
{
client = memoryAlloc(sizeof(socket_t));
if((client->sock = accept(server.sock, (SOCKADDR *)&(client->data), &clientDataSize)) != INVALID_SOCKET)
{
clientNumber++;
pthread_create(&(client->clientThread), 0, clientManager, client);
client = NULL;
}
}
return 0;
}
|
Mais ici, j'ai l'impression que le serveur n'envois que la structure globale OtherClientInfo du client et non celle de tout les clients ...
Dans tous les cas, merci pour ton intervention ! |
|
|
|
 |
|
 |
|
Page 1 sur 1
|
|
Vous ne pouvez pas poster de nouveaux sujets dans ce forum Vous ne pouvez pas répondre aux sujets dans ce forum Vous ne pouvez pas éditer vos messages dans ce forum Vous ne pouvez pas supprimer vos messages dans ce forum Vous ne pouvez pas voter dans les sondages de ce forum
|
|