Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » VC++ / MFC » Problem mit Verbindungsaufbau per Casyncsocket

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 < [ 2 ] [ 3 ] [ 4 ]
000
02.09.2003, 22:10 Uhr
~Philipp
Gast


Hi Leute,

ich habe ein ordentliches Problem mit der Netzwerkprogrammierung, habe die vor etwa einer Woche mal angefangen, aber ich bekomme das doch partout nicht richtig hin...

Habe bis jetzt leider nur das Kapitel 20 von "Visual C++6 in 21 Tagen, Markt&Technik" mit dem Thema "Internet und Netzwerkprogrammierung" gelesen, das ist eindeutig zu wenig wie ich merke.

Jedenfalls habe ich mir vorgenommen einen Chat zu programmieren.
Als System habe ich mir das halt so vorgestellt, dass es einen ChatServer und mehrere ChatClients gibt. Der ChatServer startet auf einem durch den Benutzer bestimmten Port einen Socket, und der Client connected dann ersteinmal an diesen Socket. Der ChatServer besitzt eine Liste weiterer Sockets, und er ordnet jedem Client der sich über den "Basissocket" verbinden will einen Socket aus dieser Liste zu. Ersteinmal vorab, das System sollte doch so funktionieren oder?

Mein Problem ist nun, dass ich es nicht schaffe, ein Verbindung zwischen Client und Server herzustellen! Ich schilder euch einfach mal kurz den Ablauf eines versuchten Verbindungsaufbaus:

1) ChatServer : StdSocket.Create(Port) sowie StdSocket.Listen(), StdSocket ist der Socket der nachher die Verbindunganforderung an die anderen Sockets umleitet. Der Schritt klappt (wenn ein korrekter Port übergeben wird) immer problemlos.
2) ChatClient : UserNetSocket.Create() sowie UserNetSocket.Connect(IP,Port). Connect liefer mit immer den Fehler "WSAEWOULDBLOCK". In der MSDN steht dazu folgendes: a)"If this indicates an error code of WSAEWOULDBLOCK, and your application is using the overridable callbacks, your application will receive an OnConnect message when the connect operation is complete." sowie b) "WSAEWOULDBLOCK The socket is marked as nonblocking and the connection cannot be completed immediately. ". Ich hab da jetzt verstanden, dass es einfach etwas länger dauert die Verbindung aufzubauen, ich also mit meiner Anwendung warten muss bis die Verbindung aufgebaut worden ist, was durch den Aufruf der Funktion OnConnect() bestätigt werden soll.
3) ChatClient: UserNetSocket.OnConnect wird aufgerufen. nErrorCode ist gleich 0, laut MSDN heißt das OnConnect wurde erfolgreich ausgeführt. Schön und gut, angeblich steht die Verbindung(oder?).

So, das Problem zeigt sich jetzt wenn ich Text senden will. Angeblich ist ja jetzt der Socket der ChatClient Anwendung mit einem der Sockets im Socketarray der ChatServer Anwedung verbunden, und der Datentransfer sollte klappen. Wenn ich jetzt aber dem Socket im Client sage, er solle Text schicken(halt per Send(...) Befehl, dann funktioniert das nicht. Die funktion OnReceive des mit dem Socket der ClientAnwendung verbundenen Sockets wird noch nichtmal aufgerufen, also schlägt der Datentransfer da ja irgendwie fehl. Die Frage ist halt nur, warum?

Ein paar Hilfen :

1)Wenn ich in der Eingabeaufforderung "netstat" eingebe und meine Anwendungen angeblich eine Verbindung aufgebaut haben, dann sieht man das auch(Bsp mit Port 2555):

Proto Lokale Adresse Remoteadresse Status
TCP philipp:2555 philipp:3403 HERGESTELLT
TCP philipp:3403 philipp:2555 HERGESTELLT

2)Egal welchen Text ich sende, auf dem ChatServer wird zu keiner Zeit( nicht von StdSocket und nicht von einem Socket des Arrays) die Funktion OnReceive aufgerufen.

Wüsste nun gerne warum er mir einerseits per OnConnect sagt das die Verbindung aufgebaut wurde, ich dann aber andererseits davon nichts merke.

Wenn ihr noch irgendwelche Tutorials habt, die sich mit MFC und Netzwerkprogrammierung befassen, nur her damit

Danke schonmal für die beantwortung meiner Fragen.

Philipp
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
02.09.2003, 22:39 Uhr
FloSoft
Medialer Over-Flow
(Administrator)


Hallo,
kann es sein das du beim Create Aufruf des Listen-Sockets nicht FD_READ|FD_WRITE angegeben hast?

WSAEWOULDBLOCK wird bei CAsyncSocket::Connect immer zurückgegeben, den Fehler kann man eigentlich ignorieren, ist eher eine Warnung.

Wenn der Client was sendet wird normalerweise die OnReceive-Funktion des Sockets aufgerufen, an das du den Client beim OnAccept mit dem Accept aufruf weitergeleitet hast.

Wenn du trotzdem noch Probleme damit hast und nicht weiterkommst, kannst du mir das Projekt natürlich auch gezippt/gerart/etc schicken (@ hilfe@flo-soft.de ohne Debug und Release Ordner und ohne *.exe). Ich werde es mir dann anschaun und korrigieren/ergänzen.
--
class God : public ChuckNorris { };
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
02.09.2003, 22:56 Uhr
~Philipp
Gast


Hey super, ich schau nochmal nach den Programmen, vielleicht bekomm ich es ja mit deinen Tips hin.

Sonst schick ich dir dann mal den Source an deine EMail Adresse...

THX schonmal...
Philipp
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
02.09.2003, 23:40 Uhr
~Philipp
Gast



Zitat:

kann es sein das du beim Create Aufruf des Listen-Sockets nicht FD_READ|FD_WRITE angegeben hast?



Doch das übergeb ich( ich lasse einfach die Standardparameter übergeben, und da sind FD_READ und FD_WRITE ja mit dabei).

Hups ich merke gerade, dass da noch mehr schief läuft als ich zuerst dachte.
Zwar sagt mir die Client Anwendung, dass sie eine Verbindung aufgebaut hat, jedoch bewegt sich auf der Server Seite wirklich GARNICHTS!

Normalerweise müsste doch, wenn die Client-Anwendung connect mit den richtigen Angaben aufruft, auf der Server Seite auf dem entsprechenden Socket die Funktion OnAccept() aufgerufen werden oder? Doch selbst das passiert nicht... mhhh

Kann es sein, das ich die Funktion OnAccept meines StdSocket falsch überladen habe, und der die deshalb nicht aufruft? Folgendermaßen hab ich die überladen:

void StdSocket::OnAccept(NetSocket NewNetSocket)

Philipp
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
03.09.2003, 08:56 Uhr
FloSoft
Medialer Over-Flow
(Administrator)


Du hast den Aufruf scheinbar falsch überladen:

StdSocket.h

C++:
//...
protected:
  virtual void OnAccept(int nErrorCode);
  ClientSocket m_ClientSockets[100]; // ClientSocket sollte Membervariable BOOL bOpen haben, die im Ctor mit 0 initialisiert wird
  int m_iClients;
//...



StdSocket.cpp

C++:
StdSocket::StdSocket()
{
  m_iClients = 0;
}
// ...
void StdSocket::OnAccept(int nErrorCode)
{
    m_iClients++;
  if(m_iClients < 0)
    m_iClients = 1;
  if(m_iClients <= 100)
  {
    for(int x = 0; x < 100; x++)
    {
      if(m_ClientSockets[x].bOpen == 0)
      {
        if(Accept(m_ClientSockets[x]))
        {
          // client angenommen
          m_ClientSockets[x].bOpen = 1;
        }
        else
          // fehler beim annehmen
        CAsyncSocket::OnAccept(nErrorCode);
        return;
      }
    }
  }
  iClients--;
  Close();
}
}


--
class God : public ChuckNorris { };
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
08.09.2003, 17:54 Uhr
~Philipp
Gast


Nochmal hallo,

perfekt, das klappt jetzt alles soweit! Ich kann also nachrichten senden+empfangen.

Hab jetzt allerdings ein anderes Problem:

1) Wenn ein Socket versucht sich zum Server zu verbinden, dann wird ja StdSocket::Accept(...) aufgerufen. Meine Frage ist nun, wie bekomme ich eine Referenz oder einen Zeiger auf den Socket, der sich verbinden will?

In meinem speziellen Falle möchte ich nämlich nicht, dass StdSocket die Verbindungen annimmt, sondern ich habe jetzt noch eine Klasse namens "ChatCore" hinzugefügt, und die besitzt Memberfunktionen wie "ConnectUser", "DisconnectUser", etc... Jetzt weiß ich aber nicht, wie ich die Verbindungsannahme von StdSocket::OnAccept in ChatCore::ConnectUser umleiten kann!

2) Wenn sich ein Socket Verbindet, würde ich gerne einige Benutzerdaten des mit dem Socket verbundenen Benutzers direkt im Chat anzeigen, so in der Form "User X connected on Socket Y, IP Z". Meine beiden Fragen wären jetzt:
a) wie bekomm ich die IP dieses Users
b) angenommen ich habe in der abgeleiteten Socketklasse(NetSocket in meinem falle) schon den Namen des Benutzers in einem CString gespeichert, wird diese CString Variable dann mitübertragen, sodass ich sie irgendwie auslesen kann? Un wenn ja, wie geht das dann(ist ja eigentlich die gleiche Frage wie unter 1), brauch halt irgendwie eine Referenz/Zeiger auf diesen Socket)?

Vielen vielen dank, ich weiß ich habe viele Fragen, aber ich werde in der MSDN einach nicht fündig!

Philipp
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
08.09.2003, 18:48 Uhr
FloSoft
Medialer Over-Flow
(Administrator)


Wenn ich dich richtig verstanden habe hast du die Struktur von mir oben übernommen und möchtest nun aus einer "externen" klasse auf die Member-Client-Sockets zugreifen?


Code:
| - ParentDlg
    | - ChatCore core
        | - DisconnectUser(int x)
    | - StdSocket stdsocket
        | - ClientSocket *GetClient(int x)
        | - ClientSocket m_Clients[?]




C++:
void ChatCore::DisconnectUser(int x)
{
  ParentDlg *dlg = AfxGetMainWnd();
  ClientSocket *client = dlg->stdsocket.GetClient(x);
  client->Send("kicked",7);
  client->Close();
}




C++:
ClientSocket *GetClient(int x)
{
  return &m_Clients[x];
}



Wie gesagt, keine genaue Überprüfung nach Fehlern etz..

Achja, die "gegnerische" IP bekommst du per GetPeerName(IP,Port);
--
class God : public ChuckNorris { };
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
09.09.2003, 01:56 Uhr
~Philipp
Gast


Nein, dann hab ich das falsch erklärt...

Ich muss in der Funktion StdSocket::OnAccept auf die Membervariablen der Klasse/Socket, die/der sich zu verbinden versucht, zugreifen können.

angenommen ich habe also :


Code:
class ClientSocket
{
//...
public:
  CString Name;
};



dann will ich, wenn dieser ClientSocket in StdSocket::OnAccept mit einem Socket aus dem Socketarray verbunden wird, auf die Variable "Name" zugreifen können, da ich den Namen des Users anzeigen will.


Zitat:

Achja, die "gegnerische" IP bekommst du per GetPeerName(IP,Port);


Ok, das funktioniert, danke
Wie bekomm ich aber jetzt die IP des eigenen Rechners? Hab in der MSDN GetSockName(...) gefunden, aber das liefert mir als IP immer "0.0.0.0", aber den richtigen Port!

Philipp
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
008
09.09.2003, 09:51 Uhr
FloSoft
Medialer Over-Flow
(Administrator)


wenn er 0.0.0.0 liefert hast du wahrscheinlich GetSockName bei einem nicht verbundenen Socket aufgerufen
--
class God : public ChuckNorris { };
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
009
09.09.2003, 17:32 Uhr
~Philipp
Gast



Zitat:

wenn er 0.0.0.0 liefert hast du wahrscheinlich GetSockName bei einem nicht verbundenen Socket aufgerufen


Klar, ich hab GetSockName auf den StdSocket aufgerufen, und der ist halt mit keinem Socket verbunden, sondern hört nur! Wie aber bekomm ich jetzt meine IP anders raus? Das Problem ist, dass ich die IP halt schon brauche, wenn ich nur den StdSocket erstellt habe, aber noch keinen anderen Socket erstellt habe. D.h. es gibt noch keinen Socket mit einer Verbindung zu einem anderen Socket!

>> Müsste ich als Lösung für dieses Problem 2 "dummysockets" erstellen, die ich dann miteinander verbinde, obwohl sie auf dem gleichen PC laufen? Würde das gehen?

Wegen meinem anderen Problem: Hast du / Habt ihr da keine IDee?

Philipp
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 < [ 2 ] [ 3 ] [ 4 ]     [ VC++ / MFC ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: