gpt4 book ai didi

c++ - Winsock 客户端 - 通过 TCP/IP4 连接到网络摄像机

转载 作者:行者123 更新时间:2023-11-28 05:22:35 25 4
gpt4 key购买 nike

第一个:这是我在 Stackoverflow 上的第一篇文章(如果这是错误的子论坛,请告诉我,抱歉),请原谅我的写作,因为英语不是我的母语。

因此,我正在尝试使用 winsock(客户端-服务器聊天)通过 Windows 应用程序控制高速摄像头。相机通过以太网连接,它接受到给定端口的 TCP 连接。控制流作为 TCP 流套接字实现。

控制流语法:“控制流上的所有通信都是以文本 (ASCII) 格式完成的。命令的格式使得人们可以合理地键入命令并解释结果。控制流命令解释器读取命令行并重新生成响应线。对于每个命令行,只有一个响应行。接收换行符导致命令解释器尝试执行自上一个换行符以来的所有输入作为命令。生成响应(或错误)后,命令解释器返回到它的基本状态。命令行的总长度限制为 65536 字节(包括换行符)。所有响应行都保证不会超过相同的长度。”

我已经能够与摄像机建立远程登录连接并发送/接收消息。但是:我的 C++ 客户端应用程序不会接收或发送任何消息。它说连接已成功建立。

我正在使用 Windows 10 和 Visual Studio 2015;我的代码:

///////////////////////////////////////////////////////////////////////////

// TCP Client
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#define WIN32_LEAN_AND_MEAN
#define DEFAULT_BUFLEN 512

#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#include <cstdio>
#include <iostream>

// Need to link with Ws2_32.lib
#pragma comment (lib, "Ws2_32.lib")

using namespace std;

int main()
{
int recvbuflen = DEFAULT_BUFLEN;
char sendbuf[512];
char recvbuf[DEFAULT_BUFLEN];
long rc;

WSADATA wsaData;
SOCKET sConnect = INVALID_SOCKET;
sockaddr_in serv_addr;

// ws2_32.dll activate
rc = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (rc == 0)
cout << "WSAStartup()\t\t successful" << endl;
else
cout << "error WSAStartup(): " << WSAGetLastError() << endl;

// socket configuration
sConnect = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //AF_INET for IP4
if (sConnect != INVALID_SOCKET)
cout << "socket() \t\t successful" << endl;
else
cout << "error socket(): " << WSAGetLastError() << endl;

// connection info
serv_addr.sin_addr.s_addr = inet_addr("x.x.x.x"); //Camera IP
serv_addr.sin_family = AF_INET; //IP4
serv_addr.sin_port = htons(7200); //given Port
int conparlen = sizeof(serv_addr);


// connecting to server
rc = connect(sConnect, (struct sockaddr*)&serv_addr, conparlen);
if (rc != SOCKET_ERROR)
cout << "connect() \t\t successful" << endl;
else
cout << "not connected(): " << WSAGetLastError() << endl;

while (1)
{
//memset(&sendbuf, 0, sizeof(sendbuf)); Do I need this??
//memset(&recvbuf, 0, sizeof(recvbuf));

do {
rc = recv(sConnect, recvbuf, recvbuflen, 0);
if (rc > 0)
printf("Bytes received: %d\n", rc);
else if (rc == 0)
printf("Connection closed\n");
else
printf("recv failed: %d\n", WSAGetLastError());
} while (rc > 0);

cout << "send: ";
cin.getline(sendbuf, 512);
//sendbuf[rc] = '\0';

rc = send(sConnect, sendbuf, (int)strlen(sendbuf), 0);
if (rc == SOCKET_ERROR) {
printf("send failed: %d\n", WSAGetLastError());
closesocket(sConnect);
WSACleanup();
return 1;
}

printf("Bytes Sent: %ld\n", rc);

}

closesocket(sConnect);
WSACleanup();
return 0;
}

///////////////////////////////////////////////////////////////////////////

我不明白为什么它不起作用,我是不是漏掉了什么?我很感激任何建议,谢谢!

干杯芬恩

最佳答案

您的指示非常明确:服务器的响应由一行简单的文本组成,并带有尾随换行符。

您尝试从套接字读取的代码:

do {
rc = recv(sConnect, recvbuf, recvbuflen, 0);

// a few irrelevant details here

} while (rc > 0);

这将从套接字中读取。从套接字读取内容后,...它将继续读取。它会一次又一次地阅读。直到套接字关闭。当您的相机厌倦了等待您发送评论并关闭套接字连接时,recv() 最终返回 0,您的循环终止。万岁。

这显然不是你想要的。

你想从套接字中读取,直到读取到'\n',表示接收到整行。您必须在此处相应地调整此逻辑。

我相信您知道您也不能保证一次recv() 整行。例如,如果带有响应的整行由十个字符和后跟一个换行符组成,则第一次调用 recv() 可能会返回前五个字符,而第二次调用 recv() 将返回剩余的六个字符,其中第 6 个字符是换行符。你真的不知道宇宙射线是否导致你的相机的响应在网络上变得碎片化,你的主机以碎片数据包的形式接收来自相机的整个响应,recv() 返回每个单个数据包的有效负载,一次一个。

您将需要修复您的逻辑,以便它每次都不断地从套接字读取数据,收集数据并将其附加到缓冲区中(而不是仅仅recv()将所有内容都放入同一个缓冲区中)缓冲区,覆盖之前的 recv() 的结果),并且仅在检查缓冲区收集的内容并找到换行符后才终止循环。

关于c++ - Winsock 客户端 - 通过 TCP/IP4 连接到网络摄像机,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41183932/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com