I am not an expert in C ++ nor in socket communication.
I need to connect to a server and this server should respond to my request with an XML format stream.
I have created the client (inspired by other programs) with which I try to connect to the correct IP address and port by sending a RTSP call. The connection seems to be fine, but the problem is that when I run recvfrom() I don't get any data. I tried to make a UDP client and recvfrom() returns -1.
This is the code of the UDP client:
void main(int argc, char* argv[]) {
WSADATA data;
WORD version = MAKEWORD(2, 2);
int wsOk = WSAStartup(version, &data);
if (wsOk != 0) {
cout << "can't start winsock!" << wsOk << endl;
return;
}
//create a hint structure for the server
sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = htons(80);
inet_pton(AF_INET, "192.0.0.1", &server.sin_addr);
//socket creation
SOCKET out = socket(AF_INET, SOCK_DGRAM, 0);
// write out to that socket
string s = "rtsp://pluto:paperino#192.0.0.1/media.amp?video=0&audio=0&event=on";
int sendOk = sendto(out, s.c_str(), s.size() + 1, 0, (sockaddr*)&server, sizeof(server));
if (sendOk == SOCKET_ERROR) {
cout << "That didn't work!" << WSAGetLastError() << endl;
}
else
{
cout << "connection from server is ok: " << sendOk << endl;
}
int len = sizeof(server);
char buffer[1024];
ZeroMemory(buffer, sizeof(buffer));
int recOk = 0;
recOk = recvfrom(out, buffer, sizeof(buffer), 0, (sockaddr*)&server, &len);
if (recOk != SOCKET_ERROR)
{
printf("Receive response from server: %s\n", buffer);
}
//close the socket
closesocket(out);
WSACleanup();
}
In comments, you say that recvfrom() is reporting error 10054, which is WASECONNRESET. The recvfrom() documentation on MSDN says the following about that:
Error code
Meaning
WSAECONNRESET
The virtual circuit was reset by the remote side executing a hard or abortive close. The application should close the socket; it is no longer usable. On a UDP-datagram socket this error indicates a previous send operation resulted in an ICMP Port Unreachable message.
In other words, you sent your request to a port that is not listening for UDP messages. Which makes sense, as you sent your request to port 80, which is typically used for HTTP traffic over TCP, not RTSP traffic over UDP.
For that matter, what you sent wasn't even a valid RTSP request to begin with. I suggest you read up on how the RTSP protocol actually works (hint: you don't send a rtsp:// URL with it).
Related
I try to send udp packet between on my WSL2 localhost client and server, i can sent data successfully but when want to analyze on wireshark, wireshark cannot capture anything at loopback traffic adapter and vEthernet capture. Running program and wireshark windows image at after the sender code.
sender.cpp
#define PORT 50254
int main(){
Client* client = new Client("127.0.0.1", PORT);
memset(&client->serv_addr, 0, sizeof(client->serv_addr));
client->serv_addr.sin_family = AF_INET;
client->serv_addr.sin_port = htons(port);
client->serv_addr.sin_addr.s_addr = inet_addr(client->ipAddres);
if ((client->Socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
if (connect(client->Socket, (struct sockaddr*)&client->serv_addr, sizeof(client->serv_addr)) < 0)
{
printf("\n Error : Connect Failed \n");
exit(0);
}
char* message = "Hello Server";
cout << "Sent Size : " << send(client->Socket,message, 100, 0) << endl;
}
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
I am trying to create simple server which will repond to every HTTP request with 200 OK. I write code below, but when I called the server with Postman I ended with wrong result. If I do NOT call closesocket(clientSocket), Postman is waiting infinitely long for response with Sending requst.... I i do call closesocket(clientSocket), Postman shows Error: socket hang up.
What I have to do to correctly close connection?
void main()
{
std::cout << "Start..." << std::endl;;
int port = 54000;
// Initialize WinSock
WSAData data;
WORD ver = MAKEWORD(2, 2);
int wsResult = WSAStartup(ver, &data);
if (wsResult != 0)
{
std::cout << "Can't start Winsock, Err #" << wsResult << std::endl;
return;
}
// Create socket
SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == INVALID_SOCKET)
{
std::cout << "Can't create socket, Err #" << WSAGetLastError() << std::endl;
WSACleanup();
return;
}
// Bind the ip address and port to a socket
sockaddr_in hint;
hint.sin_family = AF_INET;
hint.sin_port = htons(port);
hint.sin_addr.S_un.S_addr = INADDR_ANY;
bind(sock, (sockaddr*)&hint, sizeof(hint));
listen(sock, SOMAXCONN);
// Wait for a connection
sockaddr_in client;
int clientSize = sizeof(client);
// While loop: accept and echo message back to client
char buf[16384];
while (true)
{
SOCKET clientSocket = accept(sock, (sockaddr*)&client, &clientSize);
//print(client);
ZeroMemory(buf, 16384);
// Wait for client to send data
int bytesReceived = recv(clientSocket, buf, 16384, 0);
if (bytesReceived == SOCKET_ERROR)
{
std::cout << "Error in recv(). Quitting" << std::endl;
break;
}
const char* reply =
"HTTP/1.1 200 OK\n"
"Content-Type: text/html\n"
"Content-Length: 0\n"
"Keep - Alive: timeout=1, max=1\n"
"Accept-Ranges: bytes\n"
"Connection: close\n";
send(clientSocket, reply, strlen(reply), 0);
//closesocket(clientSocket);
} |
}
edit. Edited code. I corrected line endings, added better check for recv result and also I am checking number of sent bytes (and yes, all bytes are send). I also tried to add shutdown function, but result is still the same - infinite waiting or error. When I try to add do / while section, I will stuck in infinite waiting for another request. Do you have any other advice?
void main()
{
std::cout << "Start..." << std::endl;;
int port = 54000;
// Initialize WinSock
WSAData data;
WORD ver = MAKEWORD(2, 2);
int wsResult = WSAStartup(ver, &data);
if (wsResult != 0)
{
std::cout << "Can't start Winsock, Err #" << wsResult << std::endl;
return;
}
// Create socket
SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == INVALID_SOCKET)
{
std::cout << "Can't create socket, Err #" << WSAGetLastError() << std::endl;
WSACleanup();
return;
}
// Bind the ip address and port to a socket
sockaddr_in hint;
hint.sin_family = AF_INET;
hint.sin_port = htons(port);
hint.sin_addr.S_un.S_addr = INADDR_ANY;
bind(sock, (sockaddr*)&hint, sizeof(hint));
listen(sock, SOMAXCONN);
// Wait for a connection
sockaddr_in client;
int clientSize = sizeof(client);
// While loop: accept and echo message back to client
char buf[16384];
while (true)
{
SOCKET clientSocket = accept(sock, (sockaddr*)&client, &clientSize);
//print(client);
ZeroMemory(buf, 16384);
// Wait for client to send data
//do {
bytesReceived = recv(clientSocket, buf, 16384, 0);
if (bytesReceived > 0)
{
std::cout << std::string(buf, 0, bytesReceived) << std::endl;
}
else if (bytesReceived == 0)
{
std::cout << "Connection closed" << std::endl;
}
else
{
std::cout << "Error in recv(). Quitting = " << WSAGetLastError() << std::endl;
break;
}
//} while (bytesReceived > 0);
const char* reply =
"HTTP/1.1 200 OK\r\n"
"Content-Type: text/html\r\n"
"Content-Length: 0\r\n"
"Accept-Ranges: bytes\r\n"
"Connection: close";
bytesSent = send(clientSocket, reply, strlen(reply), 0);
if (bytesSent < 0)
{
std::cout << "Send failed = " << WSAGetLastError() << std::endl;
}
std::cout << "Sent: " << bytesSent << " (" << strlen(reply) << ")" << std::endl;
shutdown(clientSocket, SD_BOTH);
closesocket(clientSocket);
} |
}
const char* reply =
"HTTP/1.1 200 OK\n"
...
"Keep - Alive: timeout=1, max=1\n"
...
"Connection: close\n";
send(clientSocket, reply, strlen(reply), 0);
This is not a valid HTTP response for multiple reasons:
The line ending should be \r\n not \n.
The HTTP header should end with an additional \r\n (i.e. empty line). This means the HTTP response you send is not complete and thus Postman hangs on waiting for the rest.
The Keep - Alive header has not the valid syntax for a HTTP header. The field name is not allowed to contain spaces.
Apart from that,
send is not guaranteed to send everything in the given buffer, i.e. you should check the return code.
A Keep-Alive header makes no sense at all if Connection: close is used.
Note that HTTP is not an ad-hoc protocol but an actual standard. Implementations should follow the standard and thus the developers would need to study the actual standard and not blindly rely on (wrong) assumptions of how things might work. Even if it works with some client it might not work with another one, since some clients adhere more to the standard while others are more tolerant regarding errors.
There are multiple problems with the shown code.
int bytesReceived = recv(clientSocket, buf, 16384, 0);
On any TCP socket, HTTP or not, you get no guarantees whatsoever that whatever the other side of the socket sent you, it will get returned in a single recv() call.
If, for example, the client sent you the following HTTP request:
GET / HTTP/1.0<CR><LF>
Host: localhost<CR><LF>
<CR><LF>
Nobody is going to guarantee you that this recv() will return this entire thing to you. recv() could, for example, return only the "GET" part, and return the value of 3 to indicate that only 3 bytes were received. You are required to call recv() as many times as necessary to receive the complete message. The 2nd call to recv() could, theoretically, return " /" and the value of 2 to indicate that two more bytes were received.
You cannot completely ignore the return code from recv(), which tells you what was actually read, and you will need to implement appropriate logic to keep recv()ing until you received the entire message. Your code needs to understand that an HTTP message consists of a message line, an arbitrary list of headers, then a single blank line, all terminated by <CR><LF>, or "\r\n", and keep trying until it receives the complete message.
const char* reply =
"HTTP/1.1 200 OK\n"
"Content-Type: text/html\n"
"Content-Length: 0\n"
"Keep - Alive: timeout=1, max=1\n"
"Accept-Ranges: bytes\n"
"Connection: close\n";
HTTP uses <CR><LF> as the end of line terminator, all of these should be \r\n.
"Keep - Alive:" is not a valid HTTP header name. Header names cannot contain spaces.
A blank line, a single \r\n, should follow the last HTTP header. It is missing fom your response. Even though you're closing the socket immediately, without a well-formed HTTP response message the client can rightfully conclude that the HTTP server is faulty and did not send a valid response.
send(clientSocket, reply, strlen(reply), 0);
Like with recv(), you are not guaranteed that send() will transmit the requested number of bytes. Just like with recv() you must check the return value of send() to see how many bytes were sent, and then try again to send the remaining part of the message, if there's any, until you send the entire message.
You must fix all of these problems in order to properly implement HTTP over TCP.
I created TCP socket connection between client and server.
It is necessary for me to use threads because I'm getting x and y coordinates from another process, and drawing those values with OpenGL.
Only way I had in mind was to create thread for OpenGL drawing, and use main thread to recieve coordinates by socket.
My server side worked perfectly before adding #include <thread>, so I have no idea what could the problem be and why couldn't I use threads while using sockets.
After including thread, after calling recv(), I'm getting error:
WSAENOTSOCK 10038
by using WSAGetLastError();
I think that code is too long for me to post it so I can copy some parts of it that are necessary.
EDIT: code of creating socket and waiting for connection.
// Inicijaliziraj winsock
WSADATA wsData;
WORD ver = MAKEWORD(2, 2);
int wSocket = WSAStartup(ver, &wsData);
if (wSocket != 0) {
cerr << "Problem with initialization of Winsock, exiting!" << endl;
return;
}
// Create a socket
SOCKET listening = socket(AF_INET, SOCK_STREAM, 0);
if (listening == INVALID_SOCKET) {
cerr << "Unable to create a socket! Quitting" << endl;
return;
}
// Bind the ip address and port to a socket
sockaddr_in hint;
hint.sin_family = AF_INET;
hint.sin_port = htons(54000);
hint.sin_addr.S_un.S_addr = INADDR_ANY; // Could also use inet_pton
bind(listening, (sockaddr*)&hint, sizeof(hint));
// Tell winsock 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);
/*
if (clientSocket == INVALID_SOCKET) {
cerr << "Unable to connect to client socket, Quitting!" << endl;
return;
}*/
char host[NI_MAXHOST]; // Client's remote name
char service[NI_MAXHOST]; // Service (PORT) the client is connected on
ZeroMemory(host, NI_MAXHOST); // Could use memset(host, 0, )
ZeroMemory(service, NI_MAXHOST);
if (getnameinfo((sockaddr*)&client, sizeof(client), host, NI_MAXHOST, service, NI_MAXSERV, 0) == 0)
{
cout << host << " connected on port " << service << endl;
}
else
{
inet_ntop(AF_INET, &client.sin_addr, host, NI_MAXHOST);
cout << host << " connected on port " << ntohs(client.sin_port) << endl;
}
// Close listening socket
closesocket(listening);
// While loop: accept and echo message back to client
char buf[4096];
//Opens new thread with canvas because otherwise while loop for recieving will block drawing
//std::thread t1(setDrawing, &iArgc, cppArgv);
while (true) {
ZeroMemory(buf, 4096);
// Wait for client to send data
int bytesRecieved = recv(clientSocket, buf, 4096, 0);
if (bytesRecieved == SOCKET_ERROR) {
int err = WSAGetLastError();
cerr << "Error in recv(). Quitting!" << endl;
break;
}
if (bytesRecieved == 0) {
cout << "Client disconnected " << endl;
break;
}
My server side worked perfectly before adding #include <thread>, so I have no idea what could the problem be and why couldn't I use threads while using sockets.
One thing to pay attention to is that <thread> is a C++ STL header. If your code happens to have a using namespace std; statement, your socket code may end up calling the STL's std::bind() function instead of WinSock's bind() function, which would in turn cause listen() to fail with an WSAEINVAL error. Which you are not checking for since you are not doing any error handling on your bind() or listen() calls. So be aware of that. Avoid using namespace std; statements, or call WinSock's bind() as ::bind() instead. And ALWAYS do error handling on API calls.
You have also commented out your error handling on accept(). If bind() and listen() fail, so will accept(), causing it to return INVALID_SOCKET. Which could explain why you are then getting the WSAENOTSOCK error on recv().
I am currently creating a program where I require a TCP server for communication with an android application. I have written and tested the TCP server as an individual project and it runs completely fine. When including this into a larger project, where I have other processes, it no longer opens the socket for listening.
My project is being created in Visual Studio 2017 and the libraries I am using are:
WS2_32.lib for the TCP
OpenCV for image processing
Libcurl for sending files to a database
ACTi SDK for pulling image feed from a camera
The TCP server code I have written is (taken from https://www.youtube.com/watch?v=WDn-htpBlnU&t=162s):
void TCPServer()
{
//Initalize winsock
WSADATA wsData;
WORD ver = MAKEWORD(2, 2);
int wsOk = WSAStartup(ver, &wsData);
if (wsOk != 0)
{
cerr << "Can't init winsock" << endl;
return;
}
//Create a socket
SOCKET listening = socket(AF_INET, SOCK_STREAM, 0);
if (listening == INVALID_SOCKET)
{
cerr << "Can't create socket" << endl;
return;
}
//Bind the socket to an ip address and port
sockaddr_in hint;
hint.sin_family = AF_INET;
hint.sin_port = htons(100);
hint.sin_addr.S_un.S_addr = INADDR_ANY; //Could use 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]; //Clients remote name
char service[NI_MAXHOST]; //Service the client is on
ZeroMemory(host, NI_MAXHOST);
ZeroMemory(service, NI_MAXHOST);
if (getnameinfo((sockaddr*)&client, sizeof(client), host, NI_MAXHOST, service, NI_MAXSERV, 0) == 0)
{
cout << host << "connected on port " << service << endl;
}
else {
inet_ntop(AF_INET, &client.sin_addr, host, NI_MAXHOST);
cout << host << " connected on port " << ntohs(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 bytesReceived = recv(clientsocket, buf, 4096, 0);
if (bytesReceived == SOCKET_ERROR)
{
cerr << "Error in recv()" << endl;
break;
}
if (bytesReceived == 0)
{
cout << "Client disconnected" << endl;
break;
}
cout << buf << endl;
}
//Close the socket
closesocket(clientsocket);
//cleanup windsock
WSACleanup();
}
As I said, this code works as an individual project however, when I include this into my overall project the socket fails to open and a connection to 204.204.204.204 is instantly made. This was checked in both situations by viewing all open sockets with netstat. I feel this may be a library conflict, maybe between WS2_32 and libcurl, however I am unsure.
I am currently testing this by calling TCPServer() in my main, however I plan to run the server threaded along with my other processes.
Any suggestions as to why the socket may be failing to open would be much appreciated.
After carrying out checks on the function it was possible to narrow the failure down to the bind(...) function. It seems the error is down to having using namespace std;
The solution was to call bind from the global namespace by doing ::bind(...). This solution was found here: Compilation errors with socket bind function