C++ 我怎样才能得到;关闭“等待”;规格状态插座
我正在Visual Studio 2010上使用VC++。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
现在我遇到了一些问题。我觉得这个问题很傻,但我想得到一个明确的答案 如何获取所选
套接字的关闭\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;
}
}