2013-03-14 103 views
-1

我在mfc中有一個客戶端服務器應用程序,它向服務器發送消息(字符串),服務器接收消息並顯示客戶端使用的端口的IP地址一個文本框。我試圖在另一臺計算機上運行客戶端exe文件,但我收到一條錯誤消息,指出無法連接到服務器。我運行調試和釋放exe文件,所以我認爲問題是在代碼中的一些地方。無法將客戶端連接到不同計算機上的服務器

客戶端代碼:

#include "stdafx.h" 
#include "SocketTestClient.h" 
#include "SocketTestClientDlg.h" 
#include <string> 

#ifdef _DEBUG 
#define new DEBUG_NEW 
#endif 


// CAboutDlg dialog used for App About 

class CAboutDlg : public CDialog 
{ 
public: 
    CAboutDlg(); 

// Dialog Data 
    enum { IDD = IDD_ABOUTBOX }; 

    protected: 
    virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support 

// Implementation 
protected: 
    DECLARE_MESSAGE_MAP() 
}; 

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) 
{ 
} 

void CAboutDlg::DoDataExchange(CDataExchange* pDX) 
{ 
    CDialog::DoDataExchange(pDX); 
} 

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) 
END_MESSAGE_MAP() 


// CSocketTestClientDlg dialog 




CSocketTestClientDlg::CSocketTestClientDlg(CWnd* pParent /*=NULL*/) 
    : CDialog(CSocketTestClientDlg::IDD, pParent) 
    , m_senddata(_T("")) 
    , m_recvData(_T("")) 
{ 
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); 
} 

void CSocketTestClientDlg::DoDataExchange(CDataExchange* pDX) 
{ 
    CDialog::DoDataExchange(pDX); 
    DDX_Text(pDX, IDC_EDIT2, m_senddata); 
    DDX_Text(pDX, IDC_EDIT1, m_recvData); 
} 

BEGIN_MESSAGE_MAP(CSocketTestClientDlg, CDialog) 
    ON_WM_SYSCOMMAND() 
    ON_WM_PAINT() 
    ON_WM_QUERYDRAGICON() 
    //}}AFX_MSG_MAP 
    ON_BN_CLICKED(IDOK, &CSocketTestClientDlg::OnBnClickedOk) 
    ON_BN_CLICKED(IDCANCEL, &CSocketTestClientDlg::OnBnClickedCancel) 
END_MESSAGE_MAP() 


// CSocketTestClientDlg message handlers 

BOOL CSocketTestClientDlg::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 

    // TODO: Add extra initialization here 

    return TRUE; // return TRUE unless you set the focus to a control 
} 

void CSocketTestClientDlg::OnSysCommand(UINT nID, LPARAM lParam) 
{ 
    if ((nID & 0xFFF0) == IDM_ABOUTBOX) 
    { 
     CAboutDlg dlgAbout; 
     dlgAbout.DoModal(); 
    } 
    else 
    { 
     CDialog::OnSysCommand(nID, lParam); 
    } 
} 

// If you add a minimize button to your dialog, you will need the code below 
// to draw the icon. For MFC applications using the document/view model, 
// this is automatically done for you by the framework. 

void CSocketTestClientDlg::OnPaint() 
{ 
    if (IsIconic()) 
    { 
     CPaintDC dc(this); // device context for painting 

     SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0); 

     // Center icon in client rectangle 
     int cxIcon = GetSystemMetrics(SM_CXICON); 
     int cyIcon = GetSystemMetrics(SM_CYICON); 
     CRect rect; 
     GetClientRect(&rect); 
     int x = (rect.Width() - cxIcon + 1)/2; 
     int y = (rect.Height() - cyIcon + 1)/2; 

     // Draw the icon 
     dc.DrawIcon(x, y, m_hIcon); 
    } 
    else 
    { 
     CDialog::OnPaint(); 
    } 
} 

// The system calls this function to obtain the cursor to display while the user drags 
// the minimized window. 
HCURSOR CSocketTestClientDlg::OnQueryDragIcon() 
{ 
    return static_cast<HCURSOR>(m_hIcon); 
} 


void CSocketTestClientDlg::OnBnClickedOk() 
{ 

    SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 
    if(s == -1) 
    { 
     AfxMessageBox("Socket Initialiation Error"); 
    } 
    SOCKADDR_IN serveraddr; 
    struct hostent *hostentry; 


    bool bSent = false; 
    std::string server = "10.13.32.133"; 
    int portno = 1818; 

    hostentry = gethostbyname(server.c_str()); 
    char *pipaddr = inet_ntoa (*(struct in_addr *)*hostentry->h_addr_list); 

    memset(&serveraddr,0, sizeof(serveraddr)); 
    serveraddr.sin_family = AF_INET; 
    serveraddr.sin_port = htons(portno); 
    serveraddr.sin_addr.s_addr = inet_addr(pipaddr); 

    //serv_addr.sa_data = htons(portno); 

    if (connect(s,(SOCKADDR*)&serveraddr,sizeof(SOCKADDR_IN)) < 0) 
    { 
     AfxMessageBox("ERROR connecting to the server"); 
     exit(1); 
    } 

    char sbuf[1024], rbuf[1024]; 

    UpdateData(TRUE); 
    sprintf(sbuf,"%s\r\n", (const char*) m_senddata); 
    if(send(s, sbuf, strlen(sbuf), 0) == strlen(sbuf)) 
    { 
     recv(s, rbuf, 1024, 0); 
     m_recvData = rbuf; 
     UpdateData(FALSE); 
    } 
    ::closesocket(s); 
} 


void CSocketTestClientDlg::OnBnClickedCancel() 
{ 

    OnCancel(); 
} 

服務器代碼:

#include "stdafx.h" 
#include "SocketTestServer.h" 
#include "SocketTestServerDlg.h" 
#include <process.h> 
#include <string> 
#include <sys/types.h> 



#ifdef _DEBUG 
#define new DEBUG_NEW 
#endif 


// CAboutDlg dialog used for App About 

class CAboutDlg : public CDialog 
{ 
public: 
    CAboutDlg(); 

// Dialog Data 
    enum { IDD = IDD_ABOUTBOX }; 

    protected: 
    virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support 

// Implementation 
protected: 
    DECLARE_MESSAGE_MAP() 
}; 

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) 
{ 
} 

void CAboutDlg::DoDataExchange(CDataExchange* pDX) 
{ 
    CDialog::DoDataExchange(pDX); 
} 

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) 
END_MESSAGE_MAP() 


// CSocketTestServerDlg dialog 




CSocketTestServerDlg::CSocketTestServerDlg(CWnd* pParent /*=NULL*/) 
    : CDialog(CSocketTestServerDlg::IDD, pParent) 
    , m_recvData(_T("")) 
{ 
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); 
} 

void CSocketTestServerDlg::DoDataExchange(CDataExchange* pDX) 
{ 
    CDialog::DoDataExchange(pDX); 
    DDX_Text(pDX, IDC_EDIT1, m_recvData); 
} 

BEGIN_MESSAGE_MAP(CSocketTestServerDlg, CDialog) 
    ON_WM_SYSCOMMAND() 
    ON_WM_PAINT() 
    ON_WM_QUERYDRAGICON() 
    //}}AFX_MSG_MAP 
    ON_BN_CLICKED(IDOK, &CSocketTestServerDlg::OnBnClickedOk) 
    ON_WM_TIMER() 
    ON_BN_CLICKED(IDCANCEL, &CSocketTestServerDlg::OnBnClickedCancel) 
END_MESSAGE_MAP() 


// CSocketTestServerDlg message handlers 

BOOL CSocketTestServerDlg::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 

    StartServer(); 
    return TRUE; // return TRUE unless you set the focus to a control 
} 

void CSocketTestServerDlg::OnSysCommand(UINT nID, LPARAM lParam) 
{ 
    if ((nID & 0xFFF0) == IDM_ABOUTBOX) 
    { 
     CAboutDlg dlgAbout; 
     dlgAbout.DoModal(); 
    } 
    else 
    { 
     CDialog::OnSysCommand(nID, lParam); 
    } 
} 

// If you add a minimize button to your dialog, you will need the code below 
// to draw the icon. For MFC applications using the document/view model, 
// this is automatically done for you by the framework. 

void CSocketTestServerDlg::OnPaint() 
{ 
    if (IsIconic()) 
    { 
     CPaintDC dc(this); // device context for painting 

     SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0); 

     // Center icon in client rectangle 
     int cxIcon = GetSystemMetrics(SM_CXICON); 
     int cyIcon = GetSystemMetrics(SM_CYICON); 
     CRect rect; 
     GetClientRect(&rect); 
     int x = (rect.Width() - cxIcon + 1)/2; 
     int y = (rect.Height() - cyIcon + 1)/2; 

     // Draw the icon 
     dc.DrawIcon(x, y, m_hIcon); 
    } 
    else 
    { 
     CDialog::OnPaint(); 
    } 
} 

// The system calls this function to obtain the cursor to display while the user drags 
// the minimized window. 
HCURSOR CSocketTestServerDlg::OnQueryDragIcon() 
{ 
    return static_cast<HCURSOR>(m_hIcon); 
} 


void CSocketTestServerDlg::StartServer() 
{ 
    SOCKADDR_IN serveraddr; 
    int portno = 1818; 
    memset(&serveraddr,0, sizeof(serveraddr)); 
    serveraddr.sin_family = AF_INET; 
    serveraddr.sin_port = htons(portno); 
    serveraddr.sin_addr.s_addr = INADDR_ANY; 

    m_serversocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 
    if(m_serversocket == -1) 
    { 
     AfxMessageBox("Socket Initialiation Error"); 
    } 

    if(bind(m_serversocket, (SOCKADDR*)&serveraddr,sizeof(SOCKADDR_IN)) < 0) 
    { 
     AfxMessageBox("ERROR binding in the server socket"); 
     exit(1); 
    } 

    if(listen(m_serversocket,0) < 0) 
    { 
     AfxMessageBox("ERROR listening in the server socket"); 
     exit(1); 
    } 

    SetTimer(0x01, 100, NULL); 
} 

static void f(void *p) 
{ 
    CSocketTestServerDlg *pDlg = reinterpret_cast<CSocketTestServerDlg*>(p); 
    pDlg->ProcessClientRequest(); 
} 

void CSocketTestServerDlg::ProcessClientRequest() 
{ 
    SOCKADDR_IN clientaddr; 
    struct hostent *hostentry; 
    int len = sizeof(clientaddr); 
    SOCKET clientsocket = accept(m_serversocket, (sockaddr*)&clientaddr, &len); 

    if(len == -1) 
    { 
     AfxMessageBox("Error accpeting the client socket"); 
    } 
    else 
    { 
     char *p = inet_ntoa(clientaddr.sin_addr); 
     int portno = ntohs(clientaddr.sin_port); 
     // int inet_pton(int af, const char *restrict src, void *restrict dst); 

     char rbuf[1024]; 
     recv(clientsocket, rbuf, 1024, 0); 
     for(int i = 1024; i >= 1; i--) 
     { 
      if(rbuf[i] == '\n' && rbuf[i - 1] == '\r') 
      { 
       rbuf[i-1] = '\0'; 
       break; 
      } 
     } 
     CString strRecvData; 

     strRecvData.Format("%s\r\n%s %d\r\n%s\r\n\r\n", (const char*)CTime::GetCurrentTime().Format("%B %d, %Y %H:%M:%S"), p, portno, rbuf); 
     m_recvData += strRecvData; 
     m_bRefershData = true; 
     strcat(rbuf, "\r\n"); 
     send(clientsocket, rbuf, 1024, 0); 
     closesocket(clientsocket); 
    } 
} 

void CSocketTestServerDlg::OnTimer(UINT_PTR nIDEvent) 
{ 
    int idx = nIDEvent; 

    if(m_bRefershData == true) 
    { 
     m_bRefershData = false; 
     UpdateData(FALSE); 
    } 

    fd_set fds; 
    struct timeval timeout; 
    int result; 
    timeout.tv_sec = 0; 
    timeout.tv_usec = 100; 

    FD_ZERO(&fds); 
    FD_SET(m_serversocket, &fds); 

    int rc = select(sizeof(fds)*8, &fds, NULL, NULL, &timeout); 
    if (rc==-1) 
    { 
     AfxMessageBox("ERROR selecting in the server socket"); 
     return; 
    } 
    else if(rc > 0) 
    { 
     if (FD_ISSET(m_serversocket, &fds)) 
     { 
      m_bRefershData = false; 
      HANDLE h = (HANDLE) ::_beginthread(f, 0, (void*) this); 
     } 

    }   
    CDialog::OnTimer(nIDEvent); 
} 
void CSocketTestServerDlg::OnBnClickedCancel() 
{ 

    OnCancel(); 
} 

void CSocketTestServerDlg::OnBnClickedOk() 
{ 

    OnOK(); 
} 
+0

沒有人會讀那麼多的代碼。你能縮小它嗎? – 2013-03-14 11:47:14

+0

除非有人完全沒有別的事情做,否則沒有人會閱讀和調試。 – 2013-03-14 11:48:53

+0

對不起,我只是想展示一切。我猜這個錯誤是圍繞着消息AfxMessageBox(「錯誤連接到服務器」);在客戶端代碼中 - 它接近尾聲。這是當我在不同的計算機上運行客戶端時顯示的消息 – Karen123456 2013-03-14 11:50:12

回答

1

首先,看該客戶端獲取錯誤的描述。您可以這樣做:

if (connect(s,(SOCKADDR*)&serveraddr,sizeof(SOCKADDR_IN)) < 0) 
{ 
    CString msg = _T("ERROR connecting to the server: "); 
    msg += _com_error(HRESULT_FROM_WIN32(WSAGetLastError())).ErrorMessage(); 
    AfxMessageBox(msg); 
    exit(1); 
} 

您需要爲_com_error類包含comdef.h。

一個可能的問題是,服務器的計算機通過某種類型的路由器連接到互聯網,因此它不能充當服務器。

+0

謝謝你的工作。這條線做什麼? msg + = _com_error(HRESULT_FROM_WIN32(WSAGetLastError()))。ErrorMessage(); – Karen123456 2013-03-14 12:50:32

+0

它將Winsock的最後一個錯誤代碼格式化爲錯誤 – user1610015 2013-03-14 12:55:48

+0

的字符串描述,因此如果它只是描述錯誤,它是如何解決我的問題的? – Karen123456 2013-03-14 12:58:06

相關問題