无法将客户端连接到其他计算机上的服务器

can't connect client to server on different computer

本文关键字:计算机 服务器 其他 客户端 连接      更新时间:2023-10-16

我在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,"%srn", (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] = '';
                break;
            }
        }
        CString strRecvData;
        strRecvData.Format("%srn%s %drn%srnrn", (const char*)CTime::GetCurrentTime().Format("%B %d, %Y %H:%M:%S"), p, portno, rbuf);
        m_recvData += strRecvData;
        m_bRefershData = true;
        strcat(rbuf, "rn");
        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();
}

首先,看看客户端得到的错误的描述。你可以这样做:

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。

一个可能的问题是服务器的计算机是通过某种路由器连接到互联网的,所以它不能充当服务器。