简体   繁体   中英

C++ Socket Programming : Accept and Recv method do not block the process

I've been creating a socket programming code.

and I implemented server-side program as follow:

#include "Common.h"
#include "EP_Test4.h"

int main()
{
    printf("Start EP3 \n");

    while (1){
        EP_Test4 et;
    }

    return 0;
}

this is a main code. and as you can see a code line is in while-statement. in there, a class is called, the constructor in the class is also called, then the "initEntryPoint()"method is called .

EP_Test4::EP_Test4(){

    initEntryPoint();
}

in the initEntryPoint code, there are an initiation of socket method (InitCtrlSocket), a receiving data method and closing socket method.

void EP_Test4::initEntryPoint()
{   
    printf("[Waiting Restart Signal] \n");
    CSocket cCtrlEpSock;
    cCtrlEpSock.InitCtrlSocket();
    cCtrlEpSock.RecvRestartEPMsg();
    cCtrlEpSock.CloseCtrlSocket();
}

And those method are implemented like as follows

void CSocket::InitCtrlSocket(){

    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
        printf("error\r\n");
    }

    if ((EpCtrlServerSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))<0)           
    {

        perror("socket error : ");
        exit(1);
    }

    memset(&server_addr, 0, sizeof(server_addr));

    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    server_addr.sin_port = htons(6870);

    if (bind(EpCtrlServerSocket, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
    {
        perror("bind error: ");
        exit(1);
    }

    if (listen(EpCtrlServerSocket, 5)<0)
    {
        perror("listen error : ");
        exit(1);
    }

    EpCtrlClientSocket = accept(EpCtrlServerSocket, (struct sockaddr *)&client_addr, &clen);
}

void CSocket::RecvRestartEPMsg(){
    char arrRecvCompleteMsg[50];
    memset(&arrRecvCompleteMsg, 0, sizeof(arrRecvCompleteMsg));

    int data_len = recv(EpCtrlClientSocket, (char*)&arrRecvCompleteMsg, sizeof(arrRecvCompleteMsg), 0);
    cout << "RECV CTRL MSG : " << arrRecvCompleteMsg << endl;
}

void CSocket::CloseCtrlSocket(){

    closesocket(EpCtrlServerSocket);
    closesocket(EpCtrlClientSocket);
    WSACleanup();
}

But when the program is executed, the accept method and the recv method are not waiting. so printed messages are repeated like below image.

sometimes works well(waiting at the blocking method), sometimes not. I don't understand why this happen. As I know, accept method and recv method are the "blocking" method. But why those methods do sometimes block, sometimes not?

程序执行时

You have not shown enough code to diagnose your problem. And you are not doing any error handling on accept() or recv() . accept() is likely failing and you then passing an invalid socket to recv() .

I am going to go out on a limb and guess that your clen variable is uninitialized. If so, it will have a random value, causing accept() to fail if clen happens to be less than sizeof(client_addr) , and succeed if clen happens to be greater than or equal to sizeof(client_addr) .

The addrlen parameter of accept() is an IN/OUT parameter:

addrlen [in, out]
An optional pointer to an integer that contains the length of structure pointed to by the addr parameter.

...

The integer referred to by addrlen initially contains the amount of space pointed to by addr. On return it will contain the actual length in bytes of the address returned.

...

The parameter addr is a result parameter that is filled in with the address of the connecting entity, as known to the communications layer. The exact format of the addr parameter is determined by the address family in which the communication is occurring. The addrlen is a value-result parameter; it should initially contain the amount of space pointed to by addr; on return it will contain the actual length (in bytes) of the address returned.

If you don't supply the input size correctly, accept() will fail:

WSAEFAULT
The addrlen parameter is too small or addr is not a valid part of the user address space.

Try this instead:

clen = sizeof(client_addr); // <-- add this
EpCtrlClientSocket = accept(EpCtrlServerSocket, (struct sockaddr *)&client_addr, &clen);
if (EpCtrlClientSocket < 0) // <-- add this
{
    perror("accept error : ");
    exit(1);
}

void CSocket::RecvRestartEPMsg(){
    char arrRecvCompleteMsg[50];    
    int data_len = recv(EpCtrlClientSocket, arrRecvCompleteMsg, sizeof(arrRecvCompleteMsg), 0);
    if (data_len > 0) // <-- add this
    {
        cout << "RECV CTRL MSG : ";
        cout.write(arrRecvCompleteMsg, data_len);
        cout << endl;
    }
    else
        cout << "RECV CTRL ERR : " << endl;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM