Aide sockets non bloquants

Résolu
shadow1779 Messages postés 706 Date d'inscription mercredi 17 novembre 2004 Statut Membre Dernière intervention 29 septembre 2013 - 27 déc. 2005 à 13:57
cs_aardman Messages postés 1905 Date d'inscription mercredi 22 janvier 2003 Statut Membre Dernière intervention 17 septembre 2012 - 29 déc. 2005 à 16:43
il n'y a pas longtemps on m'a filé un ebook sur les sockets C avec l'API j'ai compris deux trois truc mais j'ai l'impression de caler j'aimerai qu'on me fasse un petit exemple, mon but dans mon projet est de faire une petite boite de dialogue qui receptionnera les mesage recu par le socket et une editbox afin d'envoyer au socket mes messages

voici mon codes utilisants la methodes des sockets non bloquants mais j'aimerai savoir si c'est bien comme ceci qu'il faut faire

#include <winsock2.h>
#include <windows.h>
#include <stdio.h>

#include "resource.h"

#define WM_SOCKET (WM_USER + 100)

#pragma comment(lib, "ws2_32.lib")


INT_PTR CALLBACK DlgProc(HWND, UINT, WPARAM, LPARAM);

HINSTANCE hinst;
char buffer[5000];
char ip[16];
int port;

int WINAPI WinMain(HINSTANCE Instance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
hinst = Instance;
DialogBox(hinst,(LPCTSTR)DIALOG_MAIN, 0, DlgProc);
}

/******************************************************************************/
INT_PTR CALLBACK DlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
WSADATA WSAData;
WSAStartup(MAKEWORD(2,0), &WSAData);
SOCKET sock;
SOCKADDR_IN sin;

switch (uMsg)
{
//Debut du WM_INITDIALOG
case WM_INITDIALOG:

break;

//Debut du WM_COMMAND
case WM_COMMAND:
switch(wParam)
{
case ID_CONNECT:
sock = socket(AF_INET, SOCK_STREAM, 0);
sin.sin_addr.s_addr = inet_addr(ip);
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
WSAAsyncSelect(sock,hwnd,WM_SOCKET,FD_READ | FD_WRITE);

break;
}
break;
//Fin de WM_COMMAND

case WM_SOCKET:
switch (WSAGETSELECTEVENT(lParam))
{
case FD_READ:

break;

case FD_WRITE:

break;
}
break;
//fin de WM_SOCKET

case WM_CLOSE:
EndDialog(hwnd,1);
closesocket(sock);
WSACleanup();
break;
//fin de WM_CLOSE
}
return 0;
}

.

16 réponses

cs_aardman Messages postés 1905 Date d'inscription mercredi 22 janvier 2003 Statut Membre Dernière intervention 17 septembre 2012 3
27 déc. 2005 à 20:59
Salut,

Tu trouves ca logique d'appeler WSAAsyncSelect() sur un socket que tu
n'a pas encore créé ? Il faut systematiquement traiter les erreurs de
chaque fonction winsock et afficher des messages d'erreurs en
conséquence, sinon c'est impossible de debuguer correctement un prog.

Et le WSAStartup() en haut de ta DlgProc(), il sera appelé des
centaines de fois lors de l'execution, alors que normalement il faut
l'appeler 1 fois au debut du prog seulement (il me semblait déja en
avoir parlé sur un autre thread).
3
DeAtHCrAsH Messages postés 2670 Date d'inscription vendredi 25 janvier 2002 Statut Membre Dernière intervention 6 février 2013
27 déc. 2005 à 14:18
Regarde dans mes codes tu trouveras un exemple d'application client serveur utilisant les sockets asynchrones.

Shell
0
shadow1779 Messages postés 706 Date d'inscription mercredi 17 novembre 2004 Statut Membre Dernière intervention 29 septembre 2013
27 déc. 2005 à 15:45
je m'en suis un peu basé mais rien ne marche, ca compile bien, le socket ce connect, mais aucune reception :s, revoici le code modifié

#include <winsock2.h>
#include <windows.h>
#include <stdio.h>

#include "resource.h"

#define WM_SOCKET (WM_USER + 100)

#pragma comment(lib, "ws2_32.lib")


INT_PTR CALLBACK DlgProc(HWND, UINT, WPARAM, LPARAM);

HINSTANCE hinst;
char buffer[5000];
char ip[16];
int port;
int pointeur;

int WINAPI WinMain(HINSTANCE Instance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
hinst = Instance;
DialogBox(hinst,(LPCTSTR)DIALOG_MAIN, 0, DlgProc);
}

/******************************************************************************/
INT_PTR CALLBACK DlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
WSADATA WSAData;
WSAStartup(MAKEWORD(2,0), &WSAData);
SOCKET sock;
SOCKADDR_IN sin;

switch (uMsg)
{
//Debut du WM_INITDIALOG
case WM_INITDIALOG:

break;

//Debut du WM_COMMAND
case WM_COMMAND:
switch(wParam)
{
case ID_CONNECT:
GetDlgItemText(hwnd,ID_IPCONNECT,ip,sizeof(ip));
port = GetDlgItemInt(hwnd,ID_PORT,NULL,NULL);

sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
sin.sin_addr.s_addr = inet_addr(ip);
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
if(connect(sock, (SOCKADDR *)&sin, sizeof(sin)) != SOCKET_ERROR)
{
MessageBox(NULL,"Socket Connecté!","Information",MB_ICONINFORMATION);
WSAAsyncSelect(sock,hwnd,WM_SOCKET, FD_CONNECT | FD_READ | FD_WRITE);
}
else
{
MessageBox(NULL,"Impossible d'établir la connection!","Erreur",MB_ICONEXCLAMATION);
}
break;

case ID_ENVOYER:
ZeroMemory(buffer,5000);
GetDlgItemText(hwnd,ID_SENDTEXT,buffer,sizeof(buffer));
send(sock,buffer,sizeof(buffer),0);
SendMessage(GetDlgItem(hwnd,ID_MESSAGE),EM_SETSEL,pointeur,pointeur);
SendMessage(GetDlgItem(hwnd,ID_MESSAGE),EM_REPLACESEL,TRUE,(LPARAM)buffer);
break;
}
break;
//Fin de WM_COMMAND

case WM_SOCKET:
switch (WSAGETSELECTEVENT(lParam))
{
case FD_CONNECT:

break;

case FD_READ:
ZeroMemory(buffer,5000);
recv(sock,buffer,sizeof(buffer),0);
pointeur = GetWindowTextLength(GetDlgItem(hwnd,ID_MESSAGE)) +1;
SendMessage(GetDlgItem(hwnd,ID_MESSAGE),EM_SETSEL,pointeur,pointeur);
SendMessage(GetDlgItem(hwnd,ID_MESSAGE),EM_REPLACESEL,TRUE,(LPARAM)buffer);
break;

case FD_WRITE:
break;
}
break;
//fin de WM_SOCKET

case WM_CLOSE:
EndDialog(hwnd,1);
closesocket(sock);
WSACleanup();
break;
//fin de WM_CLOSE
}
return 0;
}
0
cs_aardman Messages postés 1905 Date d'inscription mercredi 22 janvier 2003 Statut Membre Dernière intervention 17 septembre 2012 3
27 déc. 2005 à 17:41
Salut,

Si tu appeles WSAAsyncSelect() apres le connect(), le connect() sera bloquant et tu ne recevra jamais le FD_CONNECT.

De plus, sock n'est pas une variable globale donc elle n'est plus
valable lorsque tu recois un FD_READ. Tu aurais facilement remarqué ca
si tu avais fait un code avec un traitement d'erreur correct.



DeAtHCrAsH> Je pense que tu devrais arreter de donner ton code en
exemples aux debutants, car il est sujet aux meme erreurs...
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
shadow1779 Messages postés 706 Date d'inscription mercredi 17 novembre 2004 Statut Membre Dernière intervention 29 septembre 2013
27 déc. 2005 à 17:49
:s justement je me suis basé dessus c'est ca le truc :D mais alors que dois je faire concrètement pour recevoir le FD_READ en dehors de mettre WSAAsyncSelect() avant le connect
0
cs_aardman Messages postés 1905 Date d'inscription mercredi 22 janvier 2003 Statut Membre Dernière intervention 17 septembre 2012 3
27 déc. 2005 à 17:57
Salut,

Met ta variable sock en global... ou alors la déclarer en static.

static SOCKET sock; // dans ta dlgproc

elle se comportera comme une variable globale... sauf qu'elle ne sera accessible que depuis ta DlgProc().



Pour les exemples, il faut regarder dans l'ebook network2.chm et dans
ces exemples, c'est de ca qu'il faut s'inspirer car c'est la seule
source valable que je connaisse.
0
DeAtHCrAsH Messages postés 2670 Date d'inscription vendredi 25 janvier 2002 Statut Membre Dernière intervention 6 février 2013
27 déc. 2005 à 18:03
aardman> Sujets aux memes erreurs ? En quoi que je puisse corriger si nécéssaire ...

Shell
0
cs_aardman Messages postés 1905 Date d'inscription mercredi 22 janvier 2003 Statut Membre Dernière intervention 17 septembre 2012 3
27 déc. 2005 à 18:20
Salut,

DeAtHCrAsH> utiliser le FD_CONNECT pour ne pas avoir ce connect()
bloquant, voire meme le FD_CLOSE ? utiliser le HIWORD(lParam) pour
traiter les erreurs lors des evenements, utiliser le wParam pour eviter
d'avoir une variable socket globale (ou pour gerer plusieurs clients
dans le cas de ton serveur).
0
shadow1779 Messages postés 706 Date d'inscription mercredi 17 novembre 2004 Statut Membre Dernière intervention 29 septembre 2013
27 déc. 2005 à 19:11
Bon j'crois j'vai laisser tombé ca commence a me gaver, j'comprend rien du tout a quoi faire, le socket ce connecte mais recois/envoi rien, j'comprend rien du tout a ce que vous expliquez et le role réel des FD_CONNECT, FD_READ et FD_WRITE, bref j'suis encore plus largué que j'létais au debut , mais bon merci quand meme d'avoir tenté....
0
cs_aardman Messages postés 1905 Date d'inscription mercredi 22 janvier 2003 Statut Membre Dernière intervention 17 septembre 2012 3
27 déc. 2005 à 20:01
Salut,


Les sockets c'est pas evident au début, et ca ne s'apprend pas du jour
au lendemain. Si tu ne connais pas la signification des events FD_XXX
c'est qu'il te manque les bases de winsock, et donc il te sera plus
difficile de les utiliser dans tes programmes.


Personnelement je te conseille de relire le chapitre 5 de l'ebook dont
je parle si souvent (mais qui est vraiment indispensable...) ainsi que
la page msdn sur WSAAsyncSelect().
0
shadow1779 Messages postés 706 Date d'inscription mercredi 17 novembre 2004 Statut Membre Dernière intervention 29 septembre 2013
27 déc. 2005 à 20:09
ce que j'voulais dire par "je ne comprend rien" , c'est que je vois qu'il faut mettre par exemple mon script de reception des donnée dans le case FD_READ, mais il faudrai au moins que j'y arrive a ce FD_READ pour que je recoive quelque chose, et il va pas s'inventer le message qui amenera a FD_READ, si?
.
0
cs_aardman Messages postés 1905 Date d'inscription mercredi 22 janvier 2003 Statut Membre Dernière intervention 17 septembre 2012 3
27 déc. 2005 à 20:17
Salut,

Peut etre que tu les recois ce FD_READ, et que c'est le code que tu met
dans le FD_READ qui n'est pas bon.. Met ton code (a jour) ici.
0
shadow1779 Messages postés 706 Date d'inscription mercredi 17 novembre 2004 Statut Membre Dernière intervention 29 septembre 2013
27 déc. 2005 à 20:35
merci de ton attention en tout cas, tiens, dans ma boite de dialogue je me connecte sur l'ip de mon ancien server (213.246.55.23 port 21) pour tester normalement celui la devrait renvoyer "ProFTPD ...." mais rien de cela pourtant la messagebox me dis bien que le socket est ok
#include <winsock2.h>
#include <windows.h>
#include <stdio.h>

#include "resource.h"

#define WM_SOCKET (WM_USER + 100)

#pragma comment(lib, "ws2_32.lib")


INT_PTR CALLBACK DlgProc(HWND, UINT, WPARAM, LPARAM);

HINSTANCE hinst;
SOCKET sock;
SOCKADDR_IN sin;

char buffer[5000];
char ip[16];
int port;
int pointeur;

int WINAPI WinMain(HINSTANCE Instance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
hinst = Instance;
DialogBox(hinst,(LPCTSTR)DIALOG_MAIN, 0, DlgProc);
}

/******************************************************************************/
INT_PTR CALLBACK DlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
WSADATA WSAData;
WSAStartup(MAKEWORD(2,0), &WSAData);

switch (uMsg)
{
//Debut du WM_INITDIALOG
case WM_INITDIALOG:

break;

//Debut du WM_COMMAND
case WM_COMMAND:
switch(wParam)
{
case ID_CONNECT:
GetDlgItemText(hwnd,ID_IPCONNECT,ip,sizeof(ip));
port = GetDlgItemInt(hwnd,ID_PORT,NULL,NULL);

WSAAsyncSelect(sock,hwnd,WM_SOCKET, FD_CONNECT | FD_READ | FD_WRITE);
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
sin.sin_addr.s_addr = inet_addr(ip);
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
if(connect(sock, (SOCKADDR *)&sin, sizeof(sin)) != SOCKET_ERROR)
{
MessageBox(NULL,"Socket Connecté!","Information",MB_ICONINFORMATION);
}
else
{
MessageBox(NULL,"Impossible d'établir la connection!","Erreur",MB_ICONEXCLAMATION);
}
break;

case ID_ENVOYER:
ZeroMemory(buffer,5000);
GetDlgItemText(hwnd,ID_SENDTEXT,buffer,sizeof(buffer));
send(sock,buffer,sizeof(buffer),0);
SendMessage(GetDlgItem(hwnd,ID_MESSAGE),EM_SETSEL,pointeur,pointeur);
SendMessage(GetDlgItem(hwnd,ID_MESSAGE),EM_REPLACESEL,TRUE,(LPARAM)buffer);
break;
}
break;
//Fin de WM_COMMAND

case WM_SOCKET:
switch (WSAGETSELECTEVENT(lParam))
{
case FD_CONNECT:

break;

case FD_READ:
ZeroMemory(buffer,5000);
recv(sock,buffer,sizeof(buffer),0);
pointeur = GetWindowTextLength(GetDlgItem(hwnd,ID_MESSAGE)) +1;
SendMessage(GetDlgItem(hwnd,ID_MESSAGE),EM_SETSEL,pointeur,pointeur);
SendMessage(GetDlgItem(hwnd,ID_MESSAGE),EM_REPLACESEL,TRUE,(LPARAM)buffer);
break;

case FD_WRITE:
break;
}
break;
//fin de WM_SOCKET

case WM_CLOSE:
EndDialog(hwnd,1);
closesocket(sock);
WSACleanup();
break;
//fin de WM_CLOSE
}
return 0;
}
0
shadow1779 Messages postés 706 Date d'inscription mercredi 17 novembre 2004 Statut Membre Dernière intervention 29 septembre 2013
27 déc. 2005 à 22:28
J'crois tu serai une femme et a coté de moi, meme affreuse et a 350 ans j'te roulerai une pelle!!!! Ca marche a la perfection, question a part saurai tu comment on fait pour faire la meme connection mais en UDP, ya quoi a modifier, ca doit etre tout basic mais ya rien qui en parle

.
0
DeAtHCrAsH Messages postés 2670 Date d'inscription vendredi 25 janvier 2002 Statut Membre Dernière intervention 6 février 2013
28 déc. 2005 à 09:19
aardam> Je te propose de nous faire un exemple d'une application client/serveur asynchrones, codé en l'art et la manière. Si tu veux tu peux t'inspirer de mon code ih ih ih (je plaisante bien évidement ^_^ ).

On attend avec impatience ce ptit bout de code qui sera surement très utile vu le nombre de questions sur les sockets asynchrones.

Shell
0
cs_aardman Messages postés 1905 Date d'inscription mercredi 22 janvier 2003 Statut Membre Dernière intervention 17 septembre 2012 3
29 déc. 2005 à 16:43
Salut,

Si tu veux du code de réference c'est dans
http://betouchi.free.fr/doc_et_ebook/prog_reseau/exemples-network2.zip
qu'il faut regarder... pas dans mes sources.
0
Rejoignez-nous