簡體   English   中英

Winsock客戶端-通過TCP / IP4連接到網絡攝像機

[英]Winsock Client - Connecting to a Network Camera via TCP/IP4

首先:這是我在Stackoverflow上的第一篇文章(如果這是錯誤的子論壇,請讓我,對不起),請原諒我的文字,因為英語不是我的母語。

因此,即時通訊試圖使用Winsock(客戶端-服務器聊天)通過Windows應用程序控制高速攝像機。 攝像機通過以太網連接,並且確實接受到給定端口的TCP連接。 控制流實現為TCP流套接字。

控制流語法:“控制流上的所有通信均以文本(ASCII)格式進行。命令經過格式化,以便人工鍵入命令並解釋結果是合理的。控制流命令解釋器讀取命令行並生成響應行。對於每個命令行,只有一條響應行。接收換行符會使命令解釋器嘗試執行自上一個換行符以來的所有輸入作為命令。生成響應(或錯誤)后,命令解釋器返回其基本狀態。命令行的總長度限制為65536字節(包括換行符)。保證所有響應行都不會超過相同的長度。”

我已經能夠與攝像機建立telnet連接並發送/接收消息。 但是:我的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()的結果),只有在檢查了緩沖區的收集內容並找到換行符后才終止循環。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM