Chat



  • Also mein Ferienprojekt ist ein kleiner chat in einem wxWidgets Fenster.Den Chat habe ich in der Konsole angefangen und ich möchte jetzt auf Fenster umsteigen.
    Alles funktioniert ausser der Client er kann Daten senden aber empfängt keine.
    Hier mal der Code

    #include "main.h"
    #include <wx/string.h>
    
    #include <winsock2.h>
    #include <wx/textdlg.h>
       SOCKET s;
       SOCKADDR_IN addr;
       char c;
       char buf[1024];
       char inpBuf[1024];
       int inpBufPos=0;
       fd_set fdSetRead;
       TIMEVAL timeout;
       int rc;
       char* name;
    
    enum wxbuildinfoformat {
        short_f, long_f };
    
    wxString wxbuildinfo(wxbuildinfoformat format)
    {
        wxString wxbuild(wxVERSION_STRING);
    
        if (format == long_f )
        {
    #if defined(__WXMSW__)
            wxbuild << _T("-Windows");
    #elif defined(__UNIX__)
            wxbuild << _T("-Linux");
    #endif
    
    #if wxUSE_UNICODE
            wxbuild << _T("-unicode build");
    #else
            wxbuild << _T("-ANSI build");
    #endif // wxUSE_UNICODE
        }
    
        return wxbuild;
    }
    
    int idMenuQuit = wxNewId();
    int idMenuAbout = wxNewId();
    
    // wxEvent Table - Hier können EventMakros eingetragen werden
    BEGIN_EVENT_TABLE(MyFrame, wxFrame)
        EVT_MENU(idMenuQuit, MyFrame::OnQuit)
        EVT_MENU(idMenuAbout, MyFrame::OnAbout)
    END_EVENT_TABLE()
    
    MyFrame::MyFrame(wxFrame *frame, const wxString& title)
        : wxFrame(frame, -1, title)
    {
    #if wxUSE_MENUS
    	// diese Zeilen erstellen das Menü:
    	// wxMenuBar ist die eigentliche Menükomponente, welche auch später im Programm angezeigt wird...
        wxMenuBar* mbar = new wxMenuBar();
        // genau, wxMenu ist dann ein Menü...
        wxMenu* fileMenu = new wxMenu(_T(""));
        // mit Append wird ein Menüeintrag erstellt, die ID wurde oben schon im EventTable mit OnQuit verbunden.
        fileMenu->Append(idMenuQuit, _("&Quit\tAlt-F4"), _("Quit the application"));
        // das Menü in den Menubar einhängen.
        mbar->Append(fileMenu, _("&File"));
    
        wxMenu* helpMenu = new wxMenu(_T(""));
        helpMenu->Append(idMenuAbout, _("&About\tF1"), _("Show info about this application"));
        mbar->Append(helpMenu, _("&Help"));
    
    	// das Menü dem Fenster übergeben
        SetMenuBar(mbar);
    #endif // wxUSE_MENUS
    
    	// Hier wird nun der eigentliche Fensterinhalt erstellt
    	// Der Sizer wird als erstes Erstellt, weil er später die Childfenster von MyFrame aufnimmt.
    	// Die 4 Argumente sind Zeilen, Spalten, vertical gap und horizontal gap.
    	wxFlexGridSizer* sizer = new wxFlexGridSizer(2,1,0,0);
    	// Eine Besonderheit gibt es bei wxFlexGridSizer, man kann angeben, welche Spalten oder Zeilen bei einer Grössenänderung wachsen/schrumpfen sollen.
    	sizer->AddGrowableCol(0);
    	sizer->AddGrowableRow(1);
    	// Anlegen des wxButtons:
    	// Das erste Argument ist das Parent-Fenster: wxWindow* parent
    	// Das zweite Argument ist die ID des Steuerelementes: int id
    	//  wxNewId() ist ein Makro welches die nächste gültige ID zurück gibt,
    	//  alternativ kann man hier auch einen Wert aus einem Enum oder eine einfache Int variable angeben.
    	// Das dritte Argument ist die Beschriftung des Buttons.
    	chatfenster = new wxTextCtrl( this, wxID_ANY, _T("This is the log window.\n"),
                                wxPoint(5,260), wxSize(630,100),
                                wxTE_MULTILINE | wxTE_READONLY /*| wxTE_RICH*/ );
    
    	// Nach der Erzeugung übergeben wir den button dem Sizer.
    	sizer->Add(chatfenster, 0, wxALL | wxEXPAND, 5);
    	// Anlegen des wxTextCtrls:
    	// Erstes Argument ist wieder das Parent, das zweite die ID.
    	//  -1 heisst hier, das es keine Event ID innerhalb von wxWidgets braucht,
    	//  da keine Eventbindung (EventTable/Connect) vorliegt. Dies kann auch z.b. ID_DEFAULT sein, welches i.d.R. ein #define ID_DEFAULT -1 ist.
    	button = new wxButton(this,wxNewId(),_("Append Text"));
    	// Das TextCtrl dem Sizer hinzufügen, die Argumente sind hierbei:
    	// Als erstes das Steuerelement selber.
    	// Das dritte Argument sind die Sizerflags, welche das Verhalten des Steuerelmentes bei Grössenveränderungen abbildet.
    	//  wxALL stellt sicher das zu allen Seiten ein Abstand von 5 Pixeln vorhanden ist (4. Argument)
    	//  wxEXPAND - Das Steuerelement passt sich den Grössenverändungen des Fensters an
    	sizer->Add(button,0,wxALL, 5);
    	eingabe = new wxTextCtrl( this, wxID_ANY, _T("Chat Fenster\n"),
                                wxPoint(5,260), wxSize(630,100),
                                wxTE_MULTILINE  /*| wxTE_RICH*/ );
        sizer->Add(eingabe,0,wxALL|wxEXPAND, 5);
    	// Sizer dem Hauptfenster übergeben.
        SetSizer(sizer);
    
    	// korrektes Layout berechnen
    	Layout();
    	// Das Fenster bekommt eine Mindestgrösse
    	SetMinSize(wxSize(300,200));
    	// Fit stellt sicher das alle Steuerelmente ins Fenster passen, und pass notfalls diese an.
    	Fit();
    
    	// Mit Connect verbinden wir den Button-Click-Event mit der Methode OnInsertText, mit button als Event Sender.
    	Connect(button->GetId(),wxEVT_COMMAND_BUTTON_CLICKED,wxCommandEventHandler(MyFrame::OnSend));
    
    #if wxUSE_STATUSBAR
        // macht einen status balken
        CreateStatusBar(2);
        SetStatusText(_("Hello Code::Blocks user !"),0);
        SetStatusText(wxbuildinfo(short_f),1);
    #endif // wxUSE_STATUSBAR
    
       int rc;
       WSADATA wsaData;
       rc=WSAStartup(MAKEWORD(2,0),&wsaData);
    
       if(rc==SOCKET_ERROR) {
          chatfenster->AppendText("Fehler");
    
       }
       chatfenster->AppendText("Winsock started!\n");
    
    memset(&addr,0,sizeof(SOCKADDR_IN));
       addr.sin_family=AF_INET;
       addr.sin_port=htons(1234);
       addr.sin_addr.s_addr=inet_addr("127.0.0.1");
    
    s=socket(PF_INET,SOCK_STREAM,0);
       if(s==INVALID_SOCKET) {
          chatfenster->AppendText("Fehler socken kann nicht erstellt werden");
     }
     chatfenster->AppendText("Verbinden...\n");
       rc=connect(s,(SOCKADDR*)&addr,sizeof(SOCKADDR));
       if(rc==SOCKET_ERROR) {
        chatfenster->AppendText("verbinden nicht möglich");
        Close();
       }
    
       wxTextEntryDialog dlg(this,_("Gib deinen namen ein"),_("Name"),_(""));
       if(dlg.ShowModal() == wxID_OK)// AppendText fügt den Text in das TextCtrl ein. "\n" ist für den Zeilenumbruch.
       {
    wxString hname =dlg.GetValue();
    strcpy(inpBuf, (const char*)hname.mb_str(wxConvUTF8));
    name = strcat(inpBuf,"<name>");
    send(s,name,strlen(name),0);
       }
      FD_ZERO(&fdSetRead);
          FD_SET(s,&fdSetRead);
          timeout.tv_sec=0;
          timeout.tv_usec=0;
    
          while((rc=select(0,&fdSetRead,NULL,NULL,&timeout))>0) {
                rc=recv(s,buf,1023,0);
                // server hat die verbindung beendet ?
                if(rc==0) {
                    chatfenster->AppendText("Der server hat die verbindung beendet!\n");
    				Close();
    
                // fehler: beenden!
                // error: abort!
                } else if(rc==SOCKET_ERROR) {
                    chatfenster->AppendText("Error: recv failed: %d\n");
    			Close();
                }
                // empfangene daten ausgeben
                buf[rc]='\0';
                chatfenster->AppendText(wxString(buf));
    
          }
        }
    
    MyFrame::~MyFrame()
    {
    
    }
    
    void MyFrame::OnQuit(wxCommandEvent& event)
    {
        closesocket(s);
       WSACleanup();
        Close();
    }
    
    void MyFrame::OnAbout(wxCommandEvent& event)
    {
        wxString msg = wxbuildinfo(long_f);
        wxMessageBox(msg, _("Welcome to..."));
    }
    void MyFrame::OnSend(wxCommandEvent& event)
    {
    wxString value;
    value=eingabe->GetValue();
    strcpy(inpBuf, (const char*)value.mb_str(wxConvUTF8));
    rc=send(s,inpBuf,strlen(inpBuf),0);
    
    }
    


  • Diese Schleife

    while((rc=select(0,&fdSetRead,NULL,NULL,&timeout))>0) {
    

    beendet nie, oder? Wann sollen dann bitte die Nachrichten von Windows empfangen werden?

    Ich würde dir mal vorschlagen, du schaust dir wxSocket und die dazugehörigen Events an.


Anmelden zum Antworten