View Full Version : GUI client
Salve,
Mi scuso se inizio un argomento già trattato ma ho cercato un po' e non sono riuscito a trovare nulla..magari reindirizzatemi voi.
Allora, non devo scusarmi per l'inglese stavolta ma per la poca conoscenza si.
Sto lavorando alla tesi e mi serve una GUI che faccia da client per un'applicazione (di cui so che lavora da server con protocollo TCP/IPv4). L'applicazione in questione è la finestra di simulazione interattiva di OpenModelica (conoscete?)..
Vabbè in pratica ho creato una GUI (WxDev ed anche la MFC di VisualStudio ma sempre utilizzando i winsock.h, e quindo lo stesso codice )con vari buttons, ognuno con un messaggio pre impostato da inviare al server.
Riesce a connettersi a ad inviare il messaggio. Il problema è che lo fa solo al primo click.
Funziona anche se ad un pulsante associo più send() ma gli altri invii che provo a fare non li vede neppure.
Premetto che prima di ieri non avevo mai creato un client e che non sono espertissimo di programmazione in generale ma mi tocca farlo...
Avrò quindi sicuramente fatto qualche castroneria tipo:
-Ho copiato lo stesso codice per ogni button (non so se questo crea problemi).
-Non so se devo necessariamente prendere la risposta del server (so che la manda su una porta differente).
Cmq vi posto il codice e faccio prima...
void Project1Frm::WxButton1Click(wxCommandEvent& event)
{
WORD wVersionRequested = MAKEWORD(2,2);
WSADATA wsaData;
WSAStartup(wVersionRequested, &wsaData);
SOCKET sock;
sock=socket(AF_INET, SOCK_STREAM, 0);
SOCKADDR_IN addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
addr.sin_port = htons(port);
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
connect(sock, (struct sockaddr*)&addr, sizeof(struct sockaddr));
wxString mess;
mess="start#1#end";
send(sock,mess,strlen(mess),0);
}
/*
* WxButton2Click
*/
void Project1Frm::WxButton2Click(wxCommandEvent& event)
{
WORD wVersionRequested = MAKEWORD(2,2);
WSADATA wsaData;
WSAStartup(wVersionRequested, &wsaData);
SOCKET sock;
SOCKADDR_IN addr;
short port;
port = 10501;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
addr.sin_port = htons(port);
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
connect(sock, (struct sockaddr*)&addr, sizeof(struct sockaddr));
wxString mess;
mess="stop#2#end";;
send(sock,mess,strlen(mess),0);
}
So che manca la chiusura del socket e il rilascio delle librerie ma avevo pensato di farli in un altro button.
Grazie mille per l'attenzione
Francesco
Teo@Unix
28-07-2010, 14:11
ciao,
se non mi sbaglio hai sistemato l'iniziazione del socket nella routine agganciata all'evento click del bottone "send".
Ti consiglio di spostare il codice per l'iniziazione del socket in una routine a parte.... che verrà eseguita una volta!
Il tasto eseguirà solo la send().
Scusa l'ignoranza, ma dove lo piazzo? Ci avevo pensato e lo avevo messo nella routine di creazione della finestra in modo che si connettesse appena avviata ma poi mi servivano il socket per la send..come faccio a renderlo pubblico?
OK...forse ho risolto..grazie mille..ho dichiarato sock tra i private in progettoFrm.h
Pare funzioni..vi faccio sapere tra un po'..
Ah..non mi abbandonate perche avrò ancora bisogno di voi ;)
Teo@Unix
28-07-2010, 14:42
Scusa l'ignoranza, ma dove lo piazzo? Ci avevo pensato e lo avevo messo nella routine di creazione della finestra in modo che si connettesse appena avviata ma poi mi servivano il socket per la send..come faccio a renderlo pubblico?
ad esempio nel costruttore che provvederà a recuperare gli argomenti dalla GUI.
ehm..si..credo di aver fatto proprio questo..:stordita:..
Ora funziona..grazie della dritta..
Ho un'altra domanda..
Posso inizializzare più socket?..praticamente so che il server riceve dalla porta 10501 e risponde su 10500 e 10502 a seconda del tipo di risposta diciamo..
Se per esempio eseguo tre connect() con le tre diverse porte dovrebbe funzionare?..ovviamente lo chiedo perchè a me non va..o mi si blocca o semplicemente non riceve nulla..
Dalla finestra del server ottengo un "Fail to send"..può dipendere dalla dimensioni discordi delle stringhe inviate rispetto a quelle pronte a ricevere?
Teo@Unix
28-07-2010, 17:37
Si, si può inizializzare più socket.
Il problema semmai è sul lato server...
Se hai dei problemi con la send() magari posta il codice....
la dimensione dei buffer non creano problemi. La cosa fondamentale è essere sicuri di aver letto tutto ciò che c'era da leggere. Quindi devi impostare un ciclo su recv() in modo corretto. Con C++ è abbastanza semplice...
Questo l'avevo fatto in C ma rende l'idea:
// Loop per la gestione dei dati ricevuti e scrittura su disco:
while(1)
{
memset(buffer, 0, MAX);
err = WSARecv(sock, &DataBuf, 1, &lpNumberOfBytesRecvd, &lpFlags, &RecvOverLapped, 0);
if(err == -1) { mngmt_sock_error(); break; }
else TotalBytesRecvd += lpNumberOfBytesRecvd;
if(crypto_flag==1) decrypt(); // Se la connessione è crittografata devo decodificare
if(videout) cout << buffer;
if(recv_data(buffer, fplog) == -1) cerr << "Non scritto: " << buffer << endl;
}
comunque la classe C++ che stai usando per i socket dovrebbe evitarti la maggior parte del lavoro... semmai prova a cercare qualche esempio anche su MSDN, ad esempio questo è completo:
http://msdn.microsoft.com/en-us/library/ms741688(VS.85).aspx
Teo@Unix
28-07-2010, 17:43
l'esempio che ti ho messo è in C. Sono uno zuccone:doh: , prova questo qui:
http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.aspx
Scusa la risposta tarda..ma non ho avuto proprio tempo..
Allora..ho chiesto nel forum del programma "server" ma ancora nessuna risposta.
Ti posto il codice..il progetto si chiama GUIs
GUIsFrm.h
private:
//Do not add custom control declarations between
//GUI Control Declaration Start and GUI Control Declaration End.
//wxDev-C++ will remove them. Add custom code after the block.
////GUI Control Declaration Start
wxTextCtrl *WxMemo1;
wxStaticText *WxStaticText6;
wxStaticText *WxStaticText5;
wxStaticText *WxStaticText4;
wxStaticText *WxStaticText3;
wxStaticText *WxStaticText2;
wxStaticText *WxStaticText1;
wxSlider *WxSlider2;
wxSlider *WxSlider1;
wxButton *WxButton5;
wxButton *WxButton4;
wxButton *WxButton3;
wxButton *WxButton2;
wxButton *WxButton1;
////GUI Control Declaration End
SOCKET sock;
SOCKET sockIn;
SOCKET sockRes;
SOCKADDR_IN addr;
SOCKADDR_IN addr2;
SOCKADDR_IN addr3;
char buf[100];
int n;
wxString mess;
int fl;
GUIsFrm.cpp
.........
........
void GUIsFrm::WxButton1Click(wxCommandEvent& event)
{
WxMemo1->Clear();
WORD wVersionRequested = MAKEWORD(2,2);
WSADATA wsaData;
WSAStartup(wVersionRequested, &wsaData);
sock=socket(AF_INET, SOCK_STREAM, 0);
crea_addr(&addr,10501,"127.0.0.1");
connect(sock, (struct sockaddr*)&addr, sizeof(struct sockaddr));
mess="setcontrolclienturl#1#127.0.0.1#10500#end";
send(sock,mess,strlen(mess),0);
//se mi metto ad aspettare qua una risposta il programma si blocca
mess="settransferclienturl#2#127.0.0.1#10502#end";
send(sock,mess,strlen(mess),0);
//come sopra
// ora inizializzo gli altri socket
sockIn=socket(AF_INET, SOCK_STREAM, 0);
crea_addr(&addr2,10500,"127.0.0.1");
if(connect(sockIn, (struct sockaddr*)&addr2, sizeof(struct sockaddr))==0)
(*WxMemo1)<<"10500 connesso\n";
else
(*WxMemo1)<<"10500 non connesso\n Error "<<WSAGetLastError()<<"\n";
sockRes=socket(AF_INET, SOCK_STREAM, 0);
crea_addr(&addr3,10502,"127.0.0.1");
if(connect(sockRes, (struct sockaddr*)&addr3, sizeof(struct sockaddr))==0)
(*WxMemo1)<<"10502 connesso\n";
else
(*WxMemo1)<<"10502 non connesso\n Error "<<WSAGetLastError()<<"\n";
}
/*
* WxButton2Click
*/
void GUIsFrm::WxButton2Click(wxCommandEvent& event)
{
wxString mess;
mess="setfilter#3#asc:ord#val#end";
send(sock,mess,strlen(mess),0);
int n;
n=recv(sockIn,buf,sizeof(buf),0);
//mess[n]=0;
(*WxMemo1)<<buf<<"\n";
mess="start#4#end";
send(sock,mess,strlen(mess),0);
n=recv(sockIn,buf,sizeof(buf),0);
//mess[n]=0;
(*WxMemo1)<<buf<<"\n";
// insert your code here
}
/*
* WxButton3Click
*/
void GUIsFrm::WxButton3Click(wxCommandEvent& event)
{
wxString mess;
mess="pause#5#end";
send(sock,mess,strlen(mess),0);
// insert your code here
}
/*
* WxButton4Click
*/
void GUIsFrm::WxButton4Click(wxCommandEvent& event)
{
mess="stop#6#end";
send(sock,mess,strlen(mess),0);
// insert your code here
}
/*
* WxButton5Click
*/
void GUIsFrm::WxButton5Click(wxCommandEvent& event)
{
mess="shutdown#7#end";
send(sock,mess,strlen(mess),0);
closesocket(sock); // chiudo la socket
closesocket(sockIn);
closesocket(sockRes);
WSACleanup();
// insert your code here
}
//void crea_addr(struct sockaddr_in*,int , char*);
void crea_addr(struct sockaddr_in* addr,int port, char* server)
{
addr->sin_family = AF_INET;
addr->sin_addr.s_addr = inet_addr(server);
addr->sin_port = htons(port);
}
/*
* GUIsFrmActivate
*/
void GUIsFrm::GUIsFrmActivate(wxActivateEvent& event)
{
// insert your code here
}
/*
* WxSlider1Scroll
*/
void GUIsFrm::WxSlider1Scroll(wxScrollEvent& event)
{
int slid = WxSlider1->GetValue();
snprintf(buf,100,"changevalue#%d#60.0#val=%d#end",fl,slid);
fl++;
send(sock,buf,strlen(buf),0);
buf[0]=0;
n=recv(sockIn,buf,sizeof(buf),0);
//buf[n]=0;
(*WxMemo1)<<buf<<n<<"\n";
;
// insert your code here
}
/*
* WxSlider2Scroll
*/
void GUIsFrm::WxSlider2Scroll(wxScrollEvent& event)
{
// insert your code here
}
I comandi vengono ricevuti dal server perchè posso controllare una finestra DOS e gli output..L'unico problema è che alcune send() consecutive gli arrivano insieme..a volte..ma può dipendere dal fatto che non riesce a rispondermi..non è che devo inviare le richieste con un comando diverso da send() in modo da prendere automaticamente la risposta?
Ho appena verificato che alla connect degli altri socket mi viene restituito errore 10061..ovvero
WSAECONNREFUSED
10061
Connection refused.
No connection could be made because the target computer actively refused it. This usually results from trying to connect to a service that is inactive on the foreign host—that is, one with no server application running.
Pensi che debba riscrivere il tutto seguendo il tuo link o che sia un problema del server?
La connessione che ho creato non può inviare e ricevere contemporaneamente, giusto?.
Grazie e perdonami ancora se ho risposto così tardi
HO RISOLTO :D ..scrivere su questo forum mi porta fortuna evidentemente.
Praticamente l'altra applicazione non invia risposte come server ma come client..mi è venuto in mente leggendo la scritta "fail to send" e per l'errore 10061..ho quindi creato anche un server nella GUI che ascolta le risposte del programma esterno..
Grazie mille!
Saluti
Francesco.
P.S.:se dovessi aver bisogno di ulteriori info sull'argomento posso scrivere qua o devo creare una nuova discussione?
Teo@Unix
29-07-2010, 15:31
Bene.
Secondo me se gli altri post riguardano la stessa applicazzione puoi continuare questo thread, ma normalmente si riapre un'altra discussione....
in questo modo chi fa delle ricerche nel forum in cerca di soluzioni ha risultati più coerenti.
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.