C++ 我怎样才能得到;关闭“等待”;规格状态插座

C++ 我怎样才能得到;关闭“等待”;规格状态插座,c++,api,sockets,networking,C++,Api,Sockets,Networking,我正在Visual Studio 2010上使用VC++。 现在我遇到了一些问题。我觉得这个问题很傻,但我想得到一个明确的答案 如何获取所选套接字的关闭\u等待状态? // SocketThreadConn.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <WinSock.h> #include <Windows.h> #pragma

我正在Visual Studio 2010上使用VC++。
现在我遇到了一些问题。我觉得这个问题很傻,但我想得到一个明确的答案

如何获取所选
套接字的
关闭\u等待
状态?

// SocketThreadConn.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <WinSock.h>
#include <Windows.h>

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

#define PR_RECORED_TIME 10*1000 // (ms)

BYTE* pByteCamData = NULL;
INT nHeight = 900;
INT nWidth = 1600;
INT nSpect = 3;
INT nSolution = nHeight * nWidth * nSpect;

VOID SendRecoredData(SOCKET socket2operation);

int _tmain(int argc, _TCHAR* argv[])
{
    pByteCamData = new BYTE[nSolution]; // <-- use [], not ()!

    //----------------------
    // Initialize Winsock.
    WSADATA wsaData;
    int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != NO_ERROR) {
        wprintf(L"WSAStartup failed with error: %d\n", iResult);
        delete[] pByteCamData;
        return 1;
    }

    //----------------------
    // Create a SOCKET for listening for
    // incoming connection requests.
    SOCKET ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (ListenSocket == INVALID_SOCKET) {
        wprintf(L"socket failed with error: %d\n", WSAGetLastError());
        WSACleanup();
        delete[] pByteCamData;
        return 1;
    }

    //----------------------
    // The sockaddr_in structure specifies the address family,
    // IP address, and port for the socket that is being bound.
    sockaddr_in service = {};
    service.sin_family = AF_INET;
    service.sin_addr.s_addr = INADDR_ANY;   // inet_addr("127.0.0.1");
    service.sin_port = htons(27015);

    if (bind(ListenSocket, (SOCKADDR *) &service, sizeof(service)) == SOCKET_ERROR) {
        wprintf(L"bind failed with error: %d\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        delete[] pByteCamData;
        return 1;
    }

    //----------------------
    // Listen for incoming connection requests.
    // on the created socket
    if (listen(ListenSocket, 1) == SOCKET_ERROR) {
        wprintf(L"listen failed with error: %d\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        delete[] pByteCamData;
        return 1;
    }

    //----------------------
    // Accept the connection.
    wprintf(L"Waiting for client to connect...\n");
    SOCKET AcceptSocket = accept(ListenSocket, NULL, NULL);
    if (AcceptSocket == INVALID_SOCKET) {
        wprintf(L"accept failed with error: %d\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        delete[] pByteCamData;
        return 1;
    }

    wprintf(L"Client connected.\n");
    SendRecoredData(AcceptSocket); // <-- logic fix!

    // No longer need client socket
    closesocket(AcceptSocket); // <-- CLOSE_WAIT fix!

    // No longer need server socket
    closesocket(ListenSocket);

    WSACleanup();

    delete[] pByteCamData;

    return 0;
}

VOID SendRecoredData(SOCKET socket2operation)
{
    if(IsSocketAlive(socket2operation) == 0)
        return;

    INT nCountDown = 5;
    INT nSentData, nNumToSend;
    BYTE *pData;

    do
    {
        if (nCountDown == 0)
        {
            nCountDown = 5;

            pData = pByteCamData;
            nNumToSend = nSolution;

            while (nNumToSend > 0) <-- send() fix!
            {
                nSentData = send(socket2operation, (char*)pData, nNumToSend, 0);
                if (SOCKET_ERROR == nSentData) {
                    wprintf(L"send failed with error: %d\n", WSAGetLastError());
                    return;
                }
                pData += nSentData;
                nNumToSend -= nSentData;
            }

            wprintf(L"Sent Camera Data OK [%d] Bytes\n", nSolution);
        }

        Sleep(PR_RECORED_TIME);
        --nCountDown;
    }
    while (TRUE);
}
INT IsSocketAlive(SOCKET socket2check)
{
    if (socket2check == INVALID_SOCKET)
        return FALSE;

    INT nError_code = -1;
    INT nError_code_size = sizeof(nError_code);
    INT nRetValue = getsockopt(socket2check, SOL_SOCKET, SO_ERROR, (CHAR*)&nError_code, &nError_code_size);

//  if (nRetValue != -1)
    {
        //      _tprintf(_T("Error getting socket error code : %d \n"), strerror(nRetValue));
    }

    if (nError_code != 0)
    {
        _tprintf(_T("Socket error : %d \n"), strerror(nError_code));
    }

    switch (nError_code)
    {
    case 0:
        return TRUE;
        break;
    case SOCKET_ERROR:
        return FALSE;
    default:
        return FALSE;
    }
}
//SocketThreadConn.cpp:定义控制台应用程序的入口点。
//
#包括“stdafx.h”
#包括
#包括
#pragma注释(lib,“ws2_32.lib”)
#定义记录时间10*1000/(毫秒)
字节*pByteCamData=NULL;
INT nHeight=900;
INT nWidth=1600;
INT nSpect=3;
INT-nSolution=nHeight*nWidth*nSpect;
VOID SendRecoredData(套接字套接字2操作);
int _tmain(int argc,_TCHAR*argv[]
{
pByteCamData=新字节[nSolution];//
那应该是

SendRecoredData(AcceptSocket);
这会导致
send()
中出现错误,您没有告诉我们,并且您永远不会关闭
AcceptSocket
。这就是导致关闭等待状态的原因。您不需要显式查找它们。只需修复您的错误即可

如何获取所选
套接字的
CLOSE\u WAIT
状态

没有用于该特定目的的Winsock API。但是,您可以检索
套接字的两个IP/端口对(通过和),然后在或相关函数的输出中查找它们。这将为您提供当前状态,甚至是所属进程

但是,您的代码中有一个bug导致了
CLOSE\u WAIT
状态-您没有关闭
accept()返回的
SOCKET
CLOSE\u WAIT
表示已建立的连接从另一个对等方接收到一个
FIN
,并等待您发送一个
FIN
并关闭连接的
套接字
句柄

修复这个bug,您就根本不需要使用
GetTcpTable()

如何检查已接受的套接字是否已建立

您也可以使用
GetTcpTable()(因为您没有从客户端读取任何数据)


话虽如此,代码中也存在其他bug

您没有正确分配
pByteCamData
。您需要使用
[]
而不是
()
。您分配的是单个
字节,其值为
nSolution
,而不是
nSolution
字节数的数组

您正在将侦听的
套接字
传递给
SendRecoredData()
,但您应该从
accept()
传递
套接字

send()
不能保证一次发送所有请求的字节。它可以发送的字节数少于请求的字节数(这可能是因为您试图一次发送大于4MB的字节数)。如果返回值小于请求的字节数,则必须调用
send()
再次发送剩余的字节。因此,在循环中调用
send()
,直到没有更多的字节可发送

尝试类似以下内容:

// SocketThreadConn.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <WinSock.h>
#include <Windows.h>

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

#define PR_RECORED_TIME 10*1000 // (ms)

BYTE* pByteCamData = NULL;
INT nHeight = 900;
INT nWidth = 1600;
INT nSpect = 3;
INT nSolution = nHeight * nWidth * nSpect;

VOID SendRecoredData(SOCKET socket2operation);

int _tmain(int argc, _TCHAR* argv[])
{
    pByteCamData = new BYTE[nSolution]; // <-- use [], not ()!

    //----------------------
    // Initialize Winsock.
    WSADATA wsaData;
    int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != NO_ERROR) {
        wprintf(L"WSAStartup failed with error: %d\n", iResult);
        delete[] pByteCamData;
        return 1;
    }

    //----------------------
    // Create a SOCKET for listening for
    // incoming connection requests.
    SOCKET ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (ListenSocket == INVALID_SOCKET) {
        wprintf(L"socket failed with error: %d\n", WSAGetLastError());
        WSACleanup();
        delete[] pByteCamData;
        return 1;
    }

    //----------------------
    // The sockaddr_in structure specifies the address family,
    // IP address, and port for the socket that is being bound.
    sockaddr_in service = {};
    service.sin_family = AF_INET;
    service.sin_addr.s_addr = INADDR_ANY;   // inet_addr("127.0.0.1");
    service.sin_port = htons(27015);

    if (bind(ListenSocket, (SOCKADDR *) &service, sizeof(service)) == SOCKET_ERROR) {
        wprintf(L"bind failed with error: %d\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        delete[] pByteCamData;
        return 1;
    }

    //----------------------
    // Listen for incoming connection requests.
    // on the created socket
    if (listen(ListenSocket, 1) == SOCKET_ERROR) {
        wprintf(L"listen failed with error: %d\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        delete[] pByteCamData;
        return 1;
    }

    //----------------------
    // Accept the connection.
    wprintf(L"Waiting for client to connect...\n");
    SOCKET AcceptSocket = accept(ListenSocket, NULL, NULL);
    if (AcceptSocket == INVALID_SOCKET) {
        wprintf(L"accept failed with error: %d\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        delete[] pByteCamData;
        return 1;
    }

    wprintf(L"Client connected.\n");
    SendRecoredData(AcceptSocket); // <-- logic fix!

    // No longer need client socket
    closesocket(AcceptSocket); // <-- CLOSE_WAIT fix!

    // No longer need server socket
    closesocket(ListenSocket);

    WSACleanup();

    delete[] pByteCamData;

    return 0;
}

VOID SendRecoredData(SOCKET socket2operation)
{
    INT nCountDown = 5;
    INT nSentData, nNumToSend;
    BYTE *pData;

    do
    {
        if (nCountDown == 0)
        {
            nCountDown = 5;

            pData = pByteCamData;
            nNumToSend = nSolution;

            while (nNumToSend > 0) <-- send() fix!
            {
                nSentData = send(socket2operation, (char*)pData, nNumToSend, 0);
                if (SOCKET_ERROR == nSentData) {
                    wprintf(L"send failed with error: %d\n", WSAGetLastError());
                    return;
                }
                pData += nSentData;
                nNumToSend -= nSentData;
            }

            wprintf(L"Sent Camera Data OK [%d] Bytes\n", nSolution);
        }

        Sleep(PR_RECORED_TIME);
        --nCountDown;
    }
    while (TRUE);
}
//SocketThreadConn.cpp:定义控制台应用程序的入口点。
//
#包括“stdafx.h”
#包括
#包括
#pragma注释(lib,“ws2_32.lib”)
#定义记录时间10*1000/(毫秒)
字节*pByteCamData=NULL;
INT nHeight=900;
INT nWidth=1600;
INT nSpect=3;
INT-nSolution=nHeight*nWidth*nSpect;
VOID SendRecoredData(套接字套接字2操作);
int _tmain(int argc,_TCHAR*argv[]
{
pByteCamData=新字节[nSolution];//
您可以使用此功能获取所选套接字的状态。
但只有
SOCKET\u错误
SOCKET\u活动


您可以根据需要更改timeout.tv_sec(1sec)

谢谢您的好意。除了
getcptable()
,是否有任何API函数可以获取所选套接字的状态?如果可能,我可以像这样轻松获取状态。例如:)
socket2accept
/=182(ex),
If(socket\u已建立!=GetState(socket2accept)){…}
。你有类似于
GetState(socket)
的函数吗?提前谢谢你。@Kaizen:“有没有API函数可以获取所选套接字的状态?”-正如我在回答的第一句话中所说:“没有Winsock API用于特定目的。”没有很好的理由像您要求的那样查询套接字状态。如果您以正确的方式开始编写套接字代码,则没有必要这样做。非常感谢。它工作正常,然后我现在可以正确地确定套接字是否已连接(
已建立
关闭_等待
'ed'))@Kaizen这个答案完全是胡说八道。套接字可读并不意味着它死了。如果存在选择错误或超时,此代码将返回猜测,并在
select()的(不可能)情况下完成垃圾处理
返回了一个正值,但没有可读取的FD。@EJP,我知道这看起来完全是胡说八道,但有没有办法只通过知道套接字值来获取套接字的状态?使用
getcptable()
?我知道没有API函数来确定套接字的状态。我认为我的答案很荒谬,但可读意味着
已建立
,而不可读意味着
已关闭
。感谢您的建议。@a.Godnov如果可读套接字上有挂起的EOS,则表示关闭等待。如果有挂起的数据,则表示EST已建立。
select()
无法告诉您是哪个。您的方法无法告诉您是哪个。您的方法无法回答问题。什么也不能回答。TCP的整个设计是,您只能通过I/O来检测网络状况。根据设计,没有拨号音,因此,任何API或实用程序方法都无法检测网络状况
// SocketThreadConn.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <WinSock.h>
#include <Windows.h>

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

#define PR_RECORED_TIME 10*1000 // (ms)

BYTE* pByteCamData = NULL;
INT nHeight = 900;
INT nWidth = 1600;
INT nSpect = 3;
INT nSolution = nHeight * nWidth * nSpect;

VOID SendRecoredData(SOCKET socket2operation);

int _tmain(int argc, _TCHAR* argv[])
{
    pByteCamData = new BYTE[nSolution]; // <-- use [], not ()!

    //----------------------
    // Initialize Winsock.
    WSADATA wsaData;
    int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != NO_ERROR) {
        wprintf(L"WSAStartup failed with error: %d\n", iResult);
        delete[] pByteCamData;
        return 1;
    }

    //----------------------
    // Create a SOCKET for listening for
    // incoming connection requests.
    SOCKET ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (ListenSocket == INVALID_SOCKET) {
        wprintf(L"socket failed with error: %d\n", WSAGetLastError());
        WSACleanup();
        delete[] pByteCamData;
        return 1;
    }

    //----------------------
    // The sockaddr_in structure specifies the address family,
    // IP address, and port for the socket that is being bound.
    sockaddr_in service = {};
    service.sin_family = AF_INET;
    service.sin_addr.s_addr = INADDR_ANY;   // inet_addr("127.0.0.1");
    service.sin_port = htons(27015);

    if (bind(ListenSocket, (SOCKADDR *) &service, sizeof(service)) == SOCKET_ERROR) {
        wprintf(L"bind failed with error: %d\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        delete[] pByteCamData;
        return 1;
    }

    //----------------------
    // Listen for incoming connection requests.
    // on the created socket
    if (listen(ListenSocket, 1) == SOCKET_ERROR) {
        wprintf(L"listen failed with error: %d\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        delete[] pByteCamData;
        return 1;
    }

    //----------------------
    // Accept the connection.
    wprintf(L"Waiting for client to connect...\n");
    SOCKET AcceptSocket = accept(ListenSocket, NULL, NULL);
    if (AcceptSocket == INVALID_SOCKET) {
        wprintf(L"accept failed with error: %d\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        delete[] pByteCamData;
        return 1;
    }

    wprintf(L"Client connected.\n");
    SendRecoredData(AcceptSocket); // <-- logic fix!

    // No longer need client socket
    closesocket(AcceptSocket); // <-- CLOSE_WAIT fix!

    // No longer need server socket
    closesocket(ListenSocket);

    WSACleanup();

    delete[] pByteCamData;

    return 0;
}

VOID SendRecoredData(SOCKET socket2operation)
{
    INT nCountDown = 5;
    INT nSentData, nNumToSend;
    BYTE *pData;

    do
    {
        if (nCountDown == 0)
        {
            nCountDown = 5;

            pData = pByteCamData;
            nNumToSend = nSolution;

            while (nNumToSend > 0) <-- send() fix!
            {
                nSentData = send(socket2operation, (char*)pData, nNumToSend, 0);
                if (SOCKET_ERROR == nSentData) {
                    wprintf(L"send failed with error: %d\n", WSAGetLastError());
                    return;
                }
                pData += nSentData;
                nNumToSend -= nSentData;
            }

            wprintf(L"Sent Camera Data OK [%d] Bytes\n", nSolution);
        }

        Sleep(PR_RECORED_TIME);
        --nCountDown;
    }
    while (TRUE);
}
#define SOCKET_ALIVE 10
#define SOCKET_DEAD 9

INT CheckSocketAlive(SOCKET socket2check)
{
    fd_set  fdR;
    struct  timeval timeout;
    timeout.tv_sec = 1;
    timeout.tv_usec = 0;
    FD_ZERO(&fdR);  
    FD_SET(socket2check, &fdR);
    switch (select(socket2check + 1, &fdR, NULL,NULL, &timeout))
    {  
    case SOCKET_ERROR:
        _tprintf(_T("\tError condition. Code : [%d]\n"), WSAGetLastError());
        return SOCKET_DEAD;
    case 0:
        return SOCKET_ALIVE;
    default:
        if ( FD_ISSET(socket2check, &fdR) )
        {
            _tprintf(_T("A read event has occurred on socket [socket2check].\n"));
            return SOCKET_DEAD;
        }
        break;
    }
}