CSocket: Warum wird OnSend oder OnReceive nicht aufgrufen?



  • Okay, scheint wohl alles zu klappen. Hab im Button den socket erstellt und vermutlich war das objekt bereits beseitigt, bevor er die nachrichten auswerten konnte.



  • Wenn ich mich nicht irre, dann kannst du die Nachrichtenbehandlung (OnReceive, OnAccept...) nur mit dem CAsyncSocket nutzen.



  • Chris++ schrieb:

    Wenn ich mich nicht irre, dann kannst du die Nachrichtenbehandlung (OnReceive, OnAccept...) nur mit dem CAsyncSocket nutzen.

    Also hab das ganze wunderbar mit CSocket hinbekommen. Nur komm ich jetzt zum Problem, dass ich keine neuen Verbindungen mehr aufbauen kann wenn die erste verbindung geschlossen wurde (egal vom server oder von selbst)

    Hab den Socker im der MainKlase (OnInit) erstellt und will immer alle 5 sekunden den Server connecten.
    Beim ersten mal klappt alles wirklich perfekt. Die weitere connect versuche erzielen keine Ergebnisse?

    Ich erhalte nur ein TryConnect 🙄

    void CServerTestDlg::OnTimer( UINT id  )
    {
    	OutputDebugString("Try connect");
    	socket.Connect( "kf2", 4440 );
    	char s_request[] = "[test]table_request\n";
    	socket.Send( s_request, strlen(s_request) );
    	socket.Close();
    }
    


  • Kann mir dabei keiner Helfen? Irgendwie beendet der die Verbindung nicht, hab mal GetLastError bei connect() abgefangen und da kommt folgende Melsung bei heraus:

    WSAEISCONN
    10056 A connect request was made on an already connected socket.

    Was mich etwas verwirrt:
    ICh erhalte eine OnClose Nachricht, und danach möchte ich connected und dabei erhalten ich den 10056 fehler. 😮



  • Poste mal etwas mehr Code (also alles was relevant ist). Die kleine Timerfunktion reicht nicht aus.



  • Ok:

    Meine Socket-Klasse:

    CMySocket.h

    class CMySocket : public CSocket
    {
    
    public:
    	//void Init();
    	virtual void OnConnect(int nErrorCode);
    	virtual void OnClose(int nErrorCode);
    
    	virtual void OnAccept(int nErrorCode);
    
    	virtual void OnReceive(int nErrorCode);
    	virtual void OnSend(int nErrorCode);
    
    };
    

    CMySocket.cpp

    #include "stdafx.h"
    
    /*void CMySocket::Init()
    {
    	//this->PumpMessages(FD_READ);
    }*/
    
    void CMySocket::OnConnect(int nErrorCode)
    {
    	CSocket::OnConnect( nErrorCode );
    	OutputDebugString( "\nOnConnect" );
    }
    
    void CMySocket::OnClose(int nErrorCode)
    {
    	CSocket::OnClose( nErrorCode );
    	OutputDebugString( "\nOnClose" );
    	this->Close();
    }
    
    void CMySocket::OnAccept(int nErrorCode)
    {
    	CSocket::OnAccept( nErrorCode );
    	OutputDebugString( "\nOnAccept" );
    }
    
    void CMySocket::OnReceive(int nErrorCode)
    {
    	CSocket::OnReceive( nErrorCode );
    	OutputDebugString( "\nOnReceive" );
    
        char *Buffer = new char[1025];
        int BufferSize = 1024;
        int Rcvd;
        //CString strRecvd;
    
        // Nachricht abholen
        Rcvd = this->Receive(Buffer, BufferSize);
    
        // Ende der Nachricht abschneiden
        Buffer[Rcvd] = NULL;
    
        // Nachricht in die CString-Variable verweisen
    	//strRecvd = pBuf;
        //AfxMessageBox(strRecvd);
    	OutputDebugString( Buffer );
    
    	free( Buffer );
    }
    
    void CMySocket::OnSend(int nErrorCode)
    {
    	CSocket::OnSend( nErrorCode );
    	OutputDebugString( "\nOnSend" );
    }
    

    Und hier der weitere Code:

    PS: es ist egal ob ich in der Timer Funktion bin oder via Button auf den Connect auslöse, beides klappt einmalig und dann nicht mehr!!

    BOOL CServerTestDlg::OnInitDialog()
    {
    	CDialog::OnInitDialog();
    
    	// Add "About..." menu item to system menu.
    
    	// IDM_ABOUTBOX must be in the system command range.
    	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
    	ASSERT(IDM_ABOUTBOX < 0xF000);
    
    	CMenu* pSysMenu = GetSystemMenu(FALSE);
    	if (pSysMenu != NULL)
    	{
    		CString strAboutMenu;
    		strAboutMenu.LoadString(IDS_ABOUTBOX);
    		if (!strAboutMenu.IsEmpty())
    		{
    			pSysMenu->AppendMenu(MF_SEPARATOR);
    			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
    		}
    	}
    
    	// Set the icon for this dialog.  The framework does this automatically
    	//  when the application's main window is not a dialog
    	SetIcon(m_hIcon, TRUE);			// Set big icon
    	SetIcon(m_hIcon, FALSE);		// Set small icon
    
    	AfxSocketInit();
    
    	socket.Create(0, SOCK_STREAM );
    
    	return TRUE;  // return TRUE  unless you set the focus to a control
    }
    
    void CServerTestDlg::OnSysCommand(UINT nID, LPARAM lParam)
    {
    	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
    	{
    		CAboutDlg dlgAbout;
    		dlgAbout.DoModal();
    	}
    	else
    	{
    		CDialog::OnSysCommand(nID, lParam);
    	}
    }
    
    void CServerTestDlg::OnBnClickedButton1()
    {
    	// HIER DER VERBINDUNGSAUFBAU
    	if( !socket.Connect( "127.0.0.1", 4440 ) )
    	{
    		char buf[100];
    		sprintf_s( buf, 100, "\n: ERror-code: %i", socket.GetLastError() );
    
    		OutputDebugString(buf);
    	}
    	else
    	{
    		char s_request[] = "[test]table_request\n";
    		socket.Send( s_request, strlen(s_request) );
    	}
    }
    
    void CServerTestDlg::OnDestroy()
    {
    	CDialog::OnDestroy();
    
    }
    
    void CServerTestDlg::OnTimer(UINT id)
    {
    
    	CDialog::OnTimer( id );
    
    	// TODO: Add your message handler code here
    }
    

    So und hier noch die zugehörige Dlg-Klasse:

    // CServerTestDlg dialog
    class CServerTestDlg : public CDialog
    {
    // Construction
    public:
    	CServerTestDlg(CWnd* pParent = NULL);	// standard constructor
    
    // Dialog Data
    	enum { IDD = IDD_SERVERTEST_DIALOG };
    
    	protected:
    	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV support
    
    // Implementation
    protected:
    	HICON m_hIcon;
    	CMySocket socket;
    
    	// Generated message map functions
    	virtual BOOL OnInitDialog();
    	afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
    	afx_msg void OnPaint();
    	afx_msg HCURSOR OnQueryDragIcon();
    	DECLARE_MESSAGE_MAP()
    public:
    	afx_msg void OnBnClickedButton1();
    public:
    	afx_msg void OnDestroy();
    	afx_msg void OnTimer( UINT );
    };
    


  • Und nu? kannst du jetzt was mit dem Code anfangen? 😕



  • Ein CSocket-Objekt kann nur einmal connected werden,
    beim zweiten mal brauchst du ein zweites Objekt.
    Ist blöd, aber nicht zu ändern.
    Hoffe, das dir das hilft



  • Bei dir ist ja nur das Problem gewesen,
    dass das Objekt zu früh zerstört wird, oder?

    Jetzt hätte ich nämlich das gleiche Problem:
    Beim Server mit OnAccept, es wird einfach nicht aufgerufen.
    Weiss wer was?



  • Sheel schrieb:

    Ein CSocket-Objekt kann nur einmal connected werden,
    beim zweiten mal brauchst du ein zweites Objekt.
    Ist blöd, aber nicht zu ändern.
    Hoffe, das dir das hilft

    Hm, d.h. für jeden connect muss ich mir einen neues Objekt erstellen (werde das mal ausprobieren und hier weiteres posten, danke für den Tipp).

    Sheel schrieb:

    Bei dir ist ja nur das Problem gewesen,
    dass das Objekt zu früh zerstört wird, oder?

    Jetzt hätte ich nämlich das gleiche Problem:
    Beim Server mit OnAccept, es wird einfach nicht aufgerufen.
    Weiss wer was?

    Trifft das nur auf OnAccept zu oder ist das ein generelles Problem?



  • Ok, scheint wohl eine Lösung zu sein, das Socket Objekt immer neu zu erstellen. Wichtig ist jedoch hierbei, dass das Objekt vor dem Connect neu erstellt wird und ACHTUNG - nach dem erfolgreichen Connect, worauf hin eine "OnReceiv" Message erwartet wird - darf das CSocket Objekt nicht gelöscht werden, da sonst diese Nachricht nicht mehr ankommt.

    Folgender Code scheint vorerst zu funktionieren:

    void MyDLG::OnConnect()
    {
    	if( m_socket ){
    		m_socket->Close();
    		delete m_socket;
    	}
    
    	// create new object
    	m_socket = new CMySocket();
    	m_socket->Create(0, SOCK_STREAM );
    	if( !m_socket->Connect( "127.0.0.1", 4440 ) )
    	{
    		OutputDebugString( "\nERROR" );
    	}
    	else
    	{
    		char s_request[] = "[test]request\n";
    		m_socket->Send( s_request, strlen(s_request) );
    	}
    }
    

    Was hier aber immer noch nicht gelöst wurde - wie man sicher eine Verbindung beendet? Zwar wird jetzt vom Server die Verbindung nach dem Übertragen geschlossen (und eine "close") nachricht geschickt, ist aber noch keine Schöne Art.

    Ich werde versuchen eine Funktion zu schreiben, damit ich die Empfangenen Daten gut handeln kann:
    zb.

    m_socket->Send( s_request, strlen(s_request) );
    void *buffer;
    DWORD dwSize;
    m_socket->Receive( &buffer, &dwSize );
    m_socket->ReceiveEx( &buffer, 1024 );
    

    Mal schauen was bei rauskommt. (Mal wieder ist JAVA unschlagbar!) 🙄



  • Zitat: Trifft das nur auf OnAccept zu oder ist das ein generelles Problem?

    Weis ich leider nicht, da OnAccept nicht geht, kommt es sowieso zu keiner anderen On...-Funktion wie OnReceive oder so.

    Client kann sich zwar erfolgreich connecten, aber
    das CSocket (oder auch CAsyncSocket, beide gleich) tut so, als wüsste
    es von keiner verbindung.

    keine ahnung, was das ist.



  • Hast du auch an "m_socket->Create(0, SOCK_STREAM ); " gedacht?

    Bzw. Beim Server m_socket->Create( PORT(zb.1234), SOCK_STREAM );



  • Natürlich, wenn man es mit CSocket macht:

    if(xyz.Create( 1234/*Port*/ ) == 0){/*Fehler*/}
    if(xyz.Listen() == 0){/*Fehler*/}

    Und danach sollte bei einem verbindeversuch
    void xyz::OnAccept(int){...} aufgerufen werden
    Machts aber nicht


Anmelden zum Antworten