客户没有正确行事

时间:2015-06-18 10:43:08

标签: c++ client server winsock

我制作了两个C ++文件,一个用于服务器,另一个用于客户端。正如您在下面的代码中看到的那样,我想向客户端显示它们已连接,以及它们的ID,但是当我尝试连接时,它会正确地清除控制台,但是不会显示它们的ID 。我注意到当我关闭服务器并且客户端仍在运行时,客户端会显示ID。不太确定问题是什么,将等待你的回复!在此先感谢,这是代码。

服务器:

// First, we'll include all the required files

#include <winsock.h>
#include <iostream>
#include <Windows.h>

using namespace std;

#pragma comment(lib, "ws2_32.lib") // Require this lib for winsock

SOCKADDR_IN addr; // This structure saves the address and ports of the server
int addrlen = sizeof(addr); // This saves the length of the address

int Counter; // Counts how many connected clients there are
SOCKET sConnect; // Socket for incoming connections
SOCKET sListen; // Socket for listening
SOCKET *Connections; // Socket for all the connections

// Init the winsock library
int InitWinSock()
{
    int Val = 0; // Make a default
    WSAData wsaData;
    WORD DllVersion = MAKEWORD(2, 1);
    Val = WSAStartup(DllVersion, &wsaData); // Initialise winsock
    return 0;
}

int main()
{
    system("color 0a"); // Change the console color to black-green
    cout << "Server Started." << endl;
    // Winsock Init
    int Val = InitWinSock();
    if(Val != 0)
    {
        // If WinSock Init fails, display an error
        MessageBoxA(NULL, "Error while starting WinSock!", "Error", MB_OK | MB_ICONERROR);
        exit(1); // Stop the procedure
    }
    Connections = (SOCKET*) calloc(64, sizeof(SOCKET));
    // Init the sockets
    sListen = socket(AF_INET, SOCK_STREAM, NULL);
    sConnect = socket(AF_INET, SOCK_STREAM, NULL);
    addr.sin_addr.s_addr = inet_addr("127.0.0.1"); // Server address, 127.0.0.1 is localhost
    addr.sin_port = htons(2222); // Server port
    addr.sin_family = AF_INET; // This is the type of connection
    bind(sListen, (SOCKADDR*)&addr, sizeof(addr)); // Bind server to address and port
    listen(sListen, 64); // Listen for any incoming connections
    while(true)
    {
        if(sConnect = accept(sListen, (SOCKADDR*)&addr, &addrlen))
        {
            Connections[Counter] = sConnect;
            char *Name = new char[64]; // The name of the client
            ZeroMemory(Name, 64); // We make the char empty
            sprintf(Name, "%i", Counter);
            send(Connections[Counter], Name, 64, NULL); // We send the ID to the client
            cout << "New Connection!" << endl;
            Counter ++; // Increase the amount of clients
        } // end if accept the connection
        Sleep(50); // Wait 50 milliseconds
    } // end while search for connections
}

客户端:

#include <iostream>
#include <winsock.h>
#include <Windows.h>

#pragma comment(lib, "ws2_32.lib")

using namespace std;

SOCKET sConnect; // The connection socket
SOCKADDR_IN addr; // The server adress

int Startup_WinSock()
{
    WSADATA wsaData;
    WORD DllVersion = MAKEWORD(2, 1);
    int Val = WSAStartup(DllVersion, &wsaData);
    return Val;
}

int main()
{
    system("color 0a");
    int Val = Startup_WinSock();
    if(Val != 0)
    {
        cout << "Can't Startup WinSock!" << endl; // Display error
        exit(1);
    }  
    sConnect = socket(AF_INET, SOCK_STREAM, NULL);
    addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    addr.sin_port = htons(2222);
    addr.sin_family = AF_INET;
    cout << "Please press [ENTER]" << endl;
    cin.get();
    Val = connect(sConnect, (SOCKADDR*)&addr, sizeof(addr)); // Connect with the server
    if(Val != 0)
    {
        cout << "Can't reach the server!" << endl;
        main (); // Try again
    }
    else
    {
        system("cls"); // Clear the screen
        int ID;
        char *nID = new char[64]; // Client's ID
        char *hello = new char[64]; // Message from the server
        ZeroMemory(nID, 64);
        ZeroMemory(hello, 64);
        recv(sConnect, nID, 64, NULL); // Receive ID from server
        recv(sConnect, hello, 64, NULL); // Receive message from the server
        ID = atoi(nID); // Cast to an int
        cout << hello << endl;
        cout << "Your ID: " << ID << endl;
        cin.get();
    }
    return 0;
}

2 个答案:

答案 0 :(得分:3)

    recv(sConnect, nID, 64, NULL); // Receive ID from server
    recv(sConnect, hello, 64, NULL); // Receive message from the server

首先,您在此处没有错误检查。您需要在整个程序中添加错误检查,否则将无法进行故障排除。

其次,这里没有消息处理。如果第一个recv获得3个字节会发生什么?您最终会将其余ID读入hello字段。

第三,你不发送任何消息。因此第二个recv将等待读取尝试失败,即服务器终止时。

答案 1 :(得分:1)

在服务器中,您只发送ID,但仅此而已,这意味着客户端将尝试接收尚未发送的内容,并在收到任何内容之前永久阻止。

哦,你在服务器上有内存泄漏,你为名称分配内存(你只清楚,但实际上没有设置任何东西),但你永远不会释放内存。无论如何都不需要动态分配。