C++ socket communication with an external device - c++

So I've an industrial controller here and I wish to communicate with this device using my pc (windows 10), over ethernet tcp/ip.
This external device (controller) is connected directly to my pc via an ethernet cable and both my pc and the external device have a static IP address within the same range.
The manufacturer of this device has its own software with which I can communicate with the device over ethernet tcp/ip, however that is for configuring and programming the device.
I would like to make a small client application that uses sockets to send some command to this controller and should read the response from the device. The device is functioning as a server.
Important to know is that the commands should be sent in hexadecimal form to the device and it responds back with a message in hexadecimal form.
I am coding this in c++ in a visual studio 2022 environment.
So far I can connect to the external device (server), but sending the command and reading the response does not seem it be working.
Another issue is that the error messages are not displayed in the console, even when I add a delay of 2 seconds everywhere.
Below is my code:
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#pragma comment (lib, "Ws2_32.lib")
#include <iostream>
#include <string.h>
#include <sstream>
#include <WinSock2.h>
#include <WS2tcpip.h>
using namespace std;
int main()
{
WSAData wsaData;
WORD DllVersion = MAKEWORD(2, 1);
if (WSAStartup(DllVersion, &wsaData) != 0)
{
cout << " Winsocket connection failed!" << endl;
Sleep(2000);
exit(1);
}
SOCKADDR_IN address;
int addressLen = sizeof(address);
IN_ADDR ipvalue;
address.sin_addr.s_addr = inet_addr("192.168.0.10");
address.sin_port = htons(9100);
address.sin_family = AF_INET;
SOCKET connection = socket(AF_INET, SOCK_STREAM, NULL);
if (connect(connection, (SOCKADDR*)&address, addressLen) == 0)
{
cout << "Connected" << endl;
Sleep(2000);
}
else
{
cout << "Error connecting to server" << endl;
Sleep(2000);
exit(1);
}
char buffer[4096];
string getInput;
do
{
cout << ">input:";
getline(cin, getInput);
if (getInput.size() > 0)
{
// send message
int sendResult = send(connection, getInput.c_str(), getInput.size() + 1, 0);
if (sendResult != SOCKET_ERROR)
{
// Wait for response from server
ZeroMemory(buffer, 4096);
int bytesReceived = recv(connection, buffer, 4096, 0);
if (bytesReceived)
{
// Response to client
cout << "SERVER> " << string(buffer, 0, bytesReceived) << endl;
Sleep(2000);
}
else
cout << "error " << endl;
Sleep(2000);
}
}
}
while (getInput.size() > 0);
}

Related

multi usage of udp port on c++ / use port multi time on c++ server

i wanna ask about how can i use port for 2 application
for example i have a program like teamspeak server use port 9987 (Default)
and i have a code with c++ to listen to this udp ports and see the packets value
but the problem is when i start teamspeak server i can't start c++ code get error 10048
this is my code
#include <iostream>
#include <WS2tcpip.h>
// Include the Winsock library (lib) file
#pragma comment (lib, "ws2_32.lib")
using namespace std;
void main()
{
WSADATA data;
WORD version = MAKEWORD(2, 2);
// Start WinSock
int wsOk = WSAStartup(version, &data);
if (wsOk != 0)
{
// Not ok! Get out quickly
cout << "Can't start Winsock! " << wsOk;
return;
}
SOCKET in = socket(AF_INET, SOCK_DGRAM, 0);
sockaddr_in serverHint;
serverHint.sin_addr.S_un.S_addr = ADDR_ANY; // Us any IP address available on the machine
serverHint.sin_family = AF_INET; // Address format is IPv4
serverHint.sin_port = htons(9987); // Convert from little to big endian
int reuse = 1;
setsockopt(in, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof(reuse));
setsockopt(in, SOL_SOCKET, 15, (const char*)&reuse, sizeof(reuse));
// Try and bind the socket to the IP and port
if (bind(in, (sockaddr*)&serverHint, sizeof(serverHint)) == SOCKET_ERROR)
{
cout << "Can't bind socket! " << WSAGetLastError() << endl;
return;
}
sockaddr_in client; // Use to hold the client information (port / ip address)
int clientLength = sizeof(client); // The size of the client information
char buf[1024];
while (true)
{
ZeroMemory(&client, clientLength); // Clear the client structure
ZeroMemory(buf, 1024); // Clear the receive buffer
int bytesIn = recvfrom(in, buf, 1024, 0, (sockaddr*)&client, &clientLength);
if (bytesIn == SOCKET_ERROR)
{
cout << "Error receiving from client " << WSAGetLastError() << endl;
continue;
}
char clientIp[256]; // Create enough space to convert the address byte array
ZeroMemory(clientIp, 256); // to string of characters
inet_ntop(AF_INET, &client.sin_addr, clientIp, 256);
cout << "Message recv from " << clientIp << " : " << buf << endl;
}
closesocket(in);
WSACleanup();
}
i get this code from youtube channel and have some edit on it and i tired from search
my edit in the code is add SO_REUSEADDR and add SO_REUSEPORT and its value is 15
any one can help ?
2 separate applications cannot listen to the same port on the same address either for TCP or UDP, OS needs to know which application to deliver an UDP packet (or which app would accept connection in case of TCP). Exception is multicast UDP, but that is a different story. If you want to intercept packets that are delivered to existing application that is completely different task and significantly more complicated. You may use existing application like Wireshark or write your own app - details on writing app for traffic interception for windows can be found here Making a program that intercepts network traffic in Windows

C++ TCP IP Client, send/recv messages overlap?

I am currently trying to create a C++ TCP IP Client that can send a specific string to a server, which makes the server send back a string with some numbers I need to use.
Specifically I need to send the string "getpos", and only that.
This works perfectly on the first loop, but on the second loop and onward. Whenever I try to send "getpos" again, it will overlap "getpos" with the numbers I previously recieved from the server and send that like:
"getpos20,123,24"
It's like the buffer or something hasn't cleared.
My program works perfectly when connecting to a Python server, but not a C++ server.
I have looked through others with similar issues, and tried various fixes. Nothing has worked so far.
Here is my current client code (on Linux):
#include <iostream>
#include <sys/types.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <string.h>
#include <string>
int main()
{
// Create a socket
int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == -1)
{
return 1;
}
// Create a hint structure for the server we're connecting with
int port = PORTHERE;
std::string ipAddress = "IPNUMBERHERE";
sockaddr_in hint;
hint.sin_family = AF_INET;
hint.sin_port = htons(port);
inet_pton(AF_INET, ipAddress.c_str(), &hint.sin_addr);
std::cout << "listening" << std::endl;
// Connect to the server on the socket
int connectRes = connect(sock, (sockaddr*)&hint, sizeof(hint));
if (connectRes == -1)
{
return 1;
}
std::cout << "connected" << std::endl;
// While loop:
char buf[4096];
int buflen = 1024;
while(true){
// Send to server
std::string getmypos = "getpos";
int sendRes = send(sock, getmypos.c_str(), getmypos.size(), 0);
if (sendRes == -1){
std::cout << "Could not send to server! Whoops!" << std::endl;
continue;
}
// Wait for response
memset(buf, 0, 4096);
int bytesReceived = recv(sock, buf, buflen, 0);
if (bytesReceived == -1)
{
std::cout << "There was an error getting response from server" << std::endl;
}
else
{
// Display response
std::cout << "SERVER> " << std::string(buf, bytesReceived) << std::endl;
sleep(1);
}
}
// Close the socket
close(sock);
return 0;
}

Sockets not sending data

I'm currently working on an instant messaging system that require a server and a client to communicate between each other.
I tried it in C++ using the default socket API.
The problem is that even if both programs (server & client) compile fine, there isn't any socket sent from the client that reaches the server.
I don't know what did I do wrong here (I went over my code like 5 times and even did it again from scratch, no success).
I used "debugs" messages to locate the problems and they all concern the processing loops that I use.
// code from the server
#include <stdio.h>
#include <tchar.h>
#include <winsock2.h>
#include <stdlib.h>
#include <iostream>
#include <thread>
#include <vector>
#include <Ws2tcpip.h>
#include <string>
int main()
{
std::locale::global(std::locale("fr-FR"));
WSAData wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
std::cout << "Error initializing winsock";
return -1;
}
SOCKET server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (server == INVALID_SOCKET)
{
std::cout << "Error initializing the socket ";
return -2;
}
const unsigned short port = 9999;
sockaddr_in addr;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(port);
addr.sin_family = AF_INET;
int res = bind(server, (sockaddr*)&addr, sizeof(addr));
if (res != 0)
{
std::cout << "Error when binding";
return -3;
}
res = listen(server, SOMAXCONN);
if (res != 0)
{
std::cout << "Error on calling listen";
return -4;
}
std::cout << "Server successfully launched" << std::endl;
char buffer[1025];
while (true)
{
sockaddr_in from = { 0 };
int addrlen = sizeof(from);
SOCKET newClient = accept(server, (SOCKADDR*)(&from), &addrlen);
if (newClient != SOCKET_ERROR)
{
std::cout << "Client connected successfully" << std::endl;
int Bytes = recv(newClient, buffer, 1024, 0);
if (Bytes <= 0)
{
break;
}
std::cout << "Message received from client : " << buffer << std::endl;
send(newClient, buffer, 1024, 0); // send it back to client
}
}
return 0;
}
// code from the client
#include <stdio.h>
#include <tchar.h>
#include <winsock2.h>
#include <stdlib.h>
#include <iostream>
#include <thread>
#include <vector>
#include <Ws2tcpip.h>
#include <string>
#define _WINSOCK_DEPRECATED_NO_WARNINGS
void sendMessage(SOCKET s);
void recvMessage(SOCKET s);
int main()
{
std::locale::global(std::locale("fr-FR"));
WSAData wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
std::cout << "Error initializing winsock";
return -1;
}
SOCKET server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (server == INVALID_SOCKET)
{
std::cout << "Error initializing the socket ";
return -2;
}
sockaddr_in addr;
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
addr.sin_family = AF_INET;
addr.sin_port = htons(9999);
int res = bind(server, (sockaddr*)&addr, sizeof(addr));
if (res != 0)
{
std::cout << "Error when binding";
return -3;
}
if (connect(server, (const sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR)
{
std::cout << "Erreur when connecting : " << WSAGetLastError() << std::endl;
return -4;
}
std::cout << "You are connected to server" << std::endl;
std::thread sending(sendMessage, server);
std::thread receiving(recvMessage, server);
sending.detach();
receiving.detach();
while (true)
{ }
return 0;
}
void sendMessage(SOCKET s)
{
while (true)
{
std::string buff;
std::cout << "Type your message :" << std::endl;
std::getline(std::cin, buff);
std::cout << std::endl;
int Bytes = send(s, buff.c_str(), 1024, 0);
if (Bytes <= 0)
{
break;
}
}
}
void recvMessage(SOCKET s)
{
while (true)
{
char buffer[1025];
int Bytes = recv(s, buffer, 1024, 0);
if (Bytes <= 0)
{
break;
}
std::cout << "The server sent : " << buffer << std::endl;
}
}
The server should display the message that a client has connected when the client is launched and displays the chat command, but the only thing displayed in the server console is the message saying that the server has launched correctly... Yet the client displays the message supposedly "received" by the server.
PS : I'm aware the code doesn't need that many "include" statements, it's just I didn't remember which ones contained which functions so I'd rather include more than not enough for anybody wanting to compile the code.
Several Things:
First, this is wrong:
send(s, buff.c_str(), 1024, 0)
You're basically telling send that the buffer it addresses is a full 1kb, and to send it all. It hasn't a clue how much memory there is actually valid, and knows nothing about terminated strings.
Second, the client setup is wrong. Don't bind to a client socket; connect is sufficient. Notice these:
int res = bind(server, (sockaddr*)&addr, sizeof(addr));
if (res != 0)
{
std::cout << "Error when binding";
return -3;
}
if (connect(server, (const sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR)
{
std::cout << "Erreur when connecting : " << WSAGetLastError() << std::endl;
return -4;
}
That bind shouldn't be there. The connect will bind to the socket if the connection can be made. Removing the bind section of the client, fixing the buffer management to be correct, and putting closesocket calls where they belong, and your program will be much further down the road to functional. There are still some question logic workflows, but at least the connectivity will be setup better.

c++ irc server doesnt send ping

I trying to make a simple irc client with c++. i am sending PASS, NICK and USER messages but server doesnt send me PING. I cant register...
this is the code:
#include <iostream>
#include <string>
#include <WS2tcpip.h>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
string ipadress = "91.217.189.58";
int port = 6667;
WSADATA ws_data;
SOCKET Skt;
int main()
{
int ws_result = WSAStartup(MAKEWORD(2, 2), &ws_data);
if (ws_result != 0)
cout << "socket cannot be initialized\n";
else
cout << "Soket initialized!\n";
Skt = socket(AF_INET, SOCK_STREAM, 0);
if (Skt == INVALID_SOCKET)
cout << "socket not created\n";
else
cout << "Socket created!\n";
sockaddr_in hint;
hint.sin_family = AF_INET;
hint.sin_port = htons(6667);
inet_pton(AF_INET, ipadress.c_str(), &hint.sin_addr);
int connection_result = connect(Skt, (sockaddr*)&hint, sizeof(hint));
if (connection_result == SOCKET_ERROR)
cout << "Socket could not connect\n";
else
cout << "Socket Connected!\n";
string channel = "JOIN #dikes\r\n";
string Pass = "PASS PASSRE";
string user = "USER guest 0 * :IRCbot\r\n";
string nick = "NICK botzzz\r\n";
char buffer[4096];//buffer to recieve messages from irc server
send(Skt, Pass.c_str(), Pass.size(), 0);
send(Skt, nick.c_str(), nick.size() , 0);
send(Skt, user.c_str(), user.size(), 0);
while (true)
{
string Pong = "PONG";
ZeroMemory(buffer, 4096);
int bytes_recieved = recv(Skt, buffer, 4096, 0);
string msg = string(buffer, 0, bytes_recieved);
cout << msg;
if (msg == "PING")
{
send(Skt, Pong.c_str(), Pong.size() + 1, 0);
}
else if (msg == "001")
{
send(Skt, channel.c_str(), channel.size(), 0);
}
}
this is the output of this code:
Soket initialized!
Socket created!
Socket Connected!
:irc.portlane.se 020 * :Please wait while we process your connection.
ERROR :Closing Link: [unknown#176.43.204.170] (Ping timeout)
Your checks don't account for \r\n
Your checks don't account for the nick parameter on the PING command
Your PASS command isn't terminated by a \r\n
Your PONG response isn't terminated by a \r\n
You've assumed a one-to-one mapping of "received data" and "lines". This is not guaranteed. It is quite possible (likely, even) that a single call to recv fills the buffer with data from zero to many complete commands/messages, possibly followed by an incomplete message!
TCP/IP doesn't know about the IRC protocol; it doesn't care about its concept of a "command" and it does not break up packets into those itemised pieces for you. You have to do that. TCP/IP just streams bytes at you.
You need to add the received bytes to a secondary buffer when they are received, then iteratively parse that buffer to extract any complete lines that have become available. (Do this properly and it'll also take care of #1)
(However, I would still expect to see the ping request in your output, so something else must also be wrong.)

C++ Winsock IP 204.204.204.204

Im trying to learn Winsock and when I try to run this code:
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <iostream>
#include <WS2tcpip.h>
#include <thread>
#include <chrono>
#pragma comment(lib, "ws2_32.lib")
using namespace std;
void main() {
// Initialize Winsock
WSAData data;
WORD ver = MAKEWORD(2, 2);
int wsOk = WSAStartup(ver, &data);
if (wsOk != 0) { cerr << "Can't start winsock! Tactical Retreat!" << endl;
return;
}
// Create socket
SOCKET listening = socket(AF_INET, SOCK_STREAM, 0);
if (listening == INVALID_SOCKET) {
cerr << "Couldn't create socket!" << endl;
return;
}
// Bind the ip address and port to a socket
sockaddr_in hint; hint.sin_family = AF_INET;
hint.sin_port = htons(3800);
hint.sin_addr.S_un.S_addr = INADDR_ANY; // or inet_pton
bind(listening, (sockaddr*)&hint, sizeof(hint));
//Tell winsock the socket is for listening
listen(listening, SOMAXCONN); // Wait for a connection
sockaddr_in client;
int clientSize = sizeof(client);
SOCKET clientSocket = accept(listening, (sockaddr*) &client, &clientSize);
char host[NI_MAXHOST]; // Client's remote name
char service[NI_MAXHOST]; // Service (i.e port)
ZeroMemory(host, NI_MAXHOST); ZeroMemory(service, NI_MAXHOST);
if (getnameinfo((sockaddr*)&client, sizeof(client), host, NI_MAXHOST, service, NI_MAXSERV, 0) == 0) {
cout << " connected on port " << service << endl; }
else { inet_ntop(AF_INET, &client.sin_addr, host, NI_MAXHOST);
cout << host << " connected on port" << htons(client.sin_port) << endl; } // Close listening socket closesocket(listening); // While loop: accept and echo message back to client
char buf[4096];
while (true) {
ZeroMemory(buf, 4096); // Wait for client to send data
int bytesRecieved = recv(clientSocket, buf, 4096, 0);
if (bytesRecieved == SOCKET_ERROR) {
cerr << "Error in recv(). Quitting" << endl;
break;
}
if (bytesRecieved == 0) {
cout << "client disconnected " << endl;
break;
} // Echo message back to client
send(clientSocket, buf, bytesRecieved * 1, 0);
}// Close
closesocket(clientSocket); // Cleanup Winsock
WSACleanup();
std::this_thread::sleep_for(std::chrono::milliseconds(10000));
}
This is a code taken from an youtube tutorial which I copied and tried to run myself. Everytime I run it, it says a client has connected with the IP address: 204.204.204.204. I've google the problem but I still can't get it to work... it seems the problem comes from:
sockaddr_in client;
int clientSize = sizeof(client);
SOCKET clientSocket = accept(listening, (sockaddr*) &client, &clientSize);
Im not sure why it's already accepting a connection. I dont see any error.
EDIT:
I made an accept check and it fails:
if (clientSocket == INVALID_SOCKET) {
cout << "error on socket" << endl;
std::this_thread::sleep_for(std::chrono::milliseconds(10000));
return;
}
So it seems &clientSize does retrieve NULL. Im not sure what to do here.