简体   繁体   中英

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

first of: this is my first post on Stackoverflow (please let me if this is the wrong sub forum, sorry) and please excuse my writing since english is not my native language.

So, im trying to control a highspeed camera with a windows application using winsock (client-server chat). The camera is connected via ethernet and it does accept TCP connections to a given port. A control stream is implemented as TCP stream socket.

Control Stream Syntax: "All communication over the control streams is done in text (ASCII) format. The commands are formatted so that it is reasonable for a human to type commands and interpret the results. The control stream command interpreter reads command lines and produces re- sponse lines. For each command line there is exactly one reponse line. Receiving a newline causes the command interpreter to attempt to execute all input since the last newline as a command. After the response (or error) is generated, the command interpreter returns to it's base state. Command lines are limited to a total length of 65536 bytes (including the newline). All response lines are guaranteed not to exceed the same length."

I already was able to establish a telnet connection to the camera and send /receive messages. BUT: my c++ client application wont receive or send any messages. It says the connection is established successfully though.

Im using Windows 10 and Visual Studio 2015; my Code:

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

// 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;
}

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

I dont get why its not working, am I missing something here? I appreciate any suggestions, thank you!

Cheers Finn

Your instructions were very clear: the response from the server consists of a simple line of text, with a trailing newline character.

Your code that attempts to read from the socket:

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

// a few irrelevant details here

} while (rc > 0);

This will read from the socket. And after something gets read from the socket, ...it will continue reading. And it will read again, again, and a again. Until the socket is closed. When your camera gets tired of waiting for you to send a comment, and closes the socket connection, recv() finally returns 0, and your loop terminates. Hooray.

That's obviously not what you want.

You want to read from the socket until '\\n' is read, indicating that the entire line is received. You will have to adjust this logic here, accordingly.

I'm sure you're aware that you are not guaranteed to recv() the entire line at once, either. If, the entire line with the response consists of ten characters followed by a newline, the first call to recv() might, for example, return the first five characters, and than the second call to recv() will return the remaining six characters, with the 6th one being a newline. You don't really know if a cosmic ray resulted in the response from your camera getting fragmented over the network, with your host receiving the entire response from the camera in fragmented packets, with recv() returning each individual packet's payload, one at a time.

You will need to fix your logic so that it keeps reading from the socket, collecting and appending the data, each time, into a buffer (rather than just recv() ing everything into the same buffer, overwriting the previous recv() 's results), and terminating the loop only after examining the collected contents of the buffer, and finding a newline character.

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