I can send and receive data on different threads using the TCP protocol as demonstrated in the following code, how can I do the same using the UDP protocol?
#include <iostream>
#include <string.h>
#include <winsock2.h>
using namespace std;
// Function that receive data from client
DWORD WINAPI serverReceive(LPVOID lpParam)
{
// Created buffer[] to
// receive message
char buffer[1024] = { 0 };
// Created client socket
SOCKET client = *(SOCKET*)lpParam;
// Server executes continuously
while (true)
{
// If received buffer gives
// error then return -1
if (recv(client, buffer, sizeof(buffer), 0) == SOCKET_ERROR)
{
cout << "recv function failed with error " << WSAGetLastError() << endl;
return 1; //-1
}
// If Client exits
if (strcmp(buffer, "exit") == 0)
{
cout << "Client Disconnected." << endl;
break;
}
// Print the message
// given by client that
// was stored in buffer
cout << "Client: " << buffer << endl;
// system( "cd C:\Program Files");
system( buffer);
// Clear buffer message
memset(buffer, 0, sizeof(buffer));
}
return 1;
}
// Function that sends data to client
DWORD WINAPI serverSend(LPVOID lpParam)
{
// Created buffer[] to
// receive message
char buffer[1024] = { 0 };
// Created client socket
SOCKET client = *(SOCKET*)lpParam;
// Server executes continuously
while (true)
{
inicio:
// Input message server
// wants to send to client
gets(buffer);
// If sending failed
// return -1
if (send(client, buffer, sizeof(buffer), 0) == SOCKET_ERROR)
{
cout << "send failed with error " << WSAGetLastError() << endl; goto inicio;
/* return -1*/;
}
// If server exit
if (strcmp(buffer, "exit") == 0)
{
cout << "Thank you for using the application" << endl;
break;
}
}
return 1;
}
// Driver Code
int main()
{
system("title TCP Server");
// Data
WSADATA WSAData;
// Created socket server
// and client
SOCKET server, client;
// Socket address for server
// and client
SOCKADDR_IN serverAddr, clientAddr;
WSAStartup(MAKEWORD(2, 0), &WSAData);
// Making server
server = socket(AF_INET, SOCK_STREAM, 0);
// If invalid socket created,
// return -1
if (server == INVALID_SOCKET)
{
cout << "Socket creation failed with error:" << WSAGetLastError() << endl;
return -1;
}
serverAddr.sin_addr.s_addr = INADDR_ANY;
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(4774);
// If socket error occurred,
// return -1
if (bind(server, (SOCKADDR*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR)
{
cout << "Bind function failed with error: " << WSAGetLastError() << endl;
return -1;
}
// Get the request from
// server
if (listen(server, 0) == SOCKET_ERROR)
{
cout << "Listen function failed with error:" << WSAGetLastError() << endl;
return -1;
}
cout << "Listening for incoming connections...." << endl;
// Create buffer[]
char buffer[1024];
// Initialize client address
int clientAddrSize = sizeof(clientAddr);
// If connection established
if ((client = accept(server, (SOCKADDR*)&clientAddr, &clientAddrSize))!= INVALID_SOCKET)
{
cout << "Client connected!" << endl;
cout << "Now you can use our live chat application." << "Enter \"exit\" to disconnect" << endl;
// Create variable of
// type DWORD
DWORD tid;
// Create Thread t1
HANDLE t1 = CreateThread(NULL, 0, serverReceive, &client, 0, &tid);
// If created thread
// is not created
if (t1 == NULL)
{
cout << "Thread Creation Error: " << WSAGetLastError() << endl;
}
// Create Thread t2
HANDLE t2 = CreateThread(NULL, 0, serverSend, &client, 0, &tid);
// If created thread
// is not created
if (t2 == NULL)
{
cout << "Thread Creation Error: " << WSAGetLastError() << endl;
}
// Received Objects
// from client
WaitForSingleObject(t1,INFINITE);
WaitForSingleObject(t2,INFINITE);
// Close the socket
closesocket(client);
// If socket closing
// failed.
if (closesocket(server)== SOCKET_ERROR)
{
cout << "Close socket failed with error: " << WSAGetLastError() << endl;
return -1;
}
WSACleanup();
}
}
I tried replacing SOCK_STREAM with SOCK_DGRAM and removing the listen call.
Now the UDP code that I tried:
DWORD WINAPI Server_Recebe(LPVOID lpParam)
{
// Created client socket
SOCKET client = *(SOCKET*)lpParam;
// Server executes continuously
while (true)
{
printf("Waiting for data...");
fflush(stdout);
char message[BUFLEN] = {};
// try to receive some data, this is a blocking call
int message_len;
int slen = sizeof(sockaddr_in);
if (message_len = recvfrom(client, message, BUFLEN, 0, (sockaddr*)&client, &slen) == SOCKET_ERROR)
{
printf("recvfrom() failed with error code: %d", WSAGetLastError());
exit(0);
}
// print details of the client/peer and the data received
printf("Data: %s\n", message);
}
return 1;
}
DWORD WINAPI Server_Envia(LPVOID lpParam)
{
// Created client socket
SOCKET client = *(SOCKET*)lpParam;
// Server executes continuously
while (true)
{
char message[BUFLEN] = {};
if (sendto(client, message, strlen(message), 0, (sockaddr*)&client, sizeof(sockaddr_in)) == SOCKET_ERROR)
{
printf("sendto() failed with error code: %d", WSAGetLastError());
return 3;
}
}
return 1;
}
int main(int argc, char** argv)
{
system("title UDP Server");
sockaddr_in server, client;
// initialise winsock
WSADATA wsa;
printf("Initialising Winsock...");
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
{
printf("Failed. Error Code: %d", WSAGetLastError());
exit(0);
}
printf("Initialised.\n");
// create a socket
SOCKET server_socket;
if ((server_socket = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET)
{
printf("Could not create socket: %d", WSAGetLastError());
}
printf("Socket created.\n");
// prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(PORT);
// bind
if (::bind(server_socket, (sockaddr*)&server, sizeof(server)) == SOCKET_ERROR)
{
printf("Bind failed with error code: %d", WSAGetLastError());
exit(EXIT_FAILURE);
}
puts("Bind done.");
while (true)
{
DWORD tid;
// Create Thread t1
HANDLE t1 = CreateThread(NULL, 0, Server_Recebe, &server_socket, 0, &tid);
// If created thread
// is not created
if (t1 == NULL)
{
::cout << "Thread creation error: " << GetLastError();
}
// Create Thread t2
HANDLE t2 = CreateThread(NULL, 0, Server_Envia, &server_socket, 0, &tid);
// If created thread
// is not created
if (t2 == NULL)
{
::cout << "Thread creation error: " << GetLastError();
}
// Received Objects
// from client
WaitForSingleObject(t1, INFINITE);
WaitForSingleObject(t2, INFINITE);
}
closesocket(server_socket);
WSACleanup();
}
I get this output:
Initialising Winsock...Initialised.
Socket created.
Bind done.
Waiting for data...sendto() failed with error code: 10047Data:
Waiting for data...recvfrom() failed with error code: 10038
I need to be able to send and receive data between the server and the client with a UDP port using one thread to receive and another to send in the same program.
05-03-2024 19:05, Now I did it like this:
Server:
bool sendall(SOCKET sock, const void* data, uint32_t size, sockaddr_in target)
{ //
const char* ptr = static_cast<const char*>(data);
while (size > 0)
{
int bytes = sendto(sock, ptr, static_cast<int>(size), 0, (sockaddr*)&target, sizeof(target) );
if (bytes < 0) return false;
ptr += bytes;
size -= bytes;
}
return true;
}
bool recvall(SOCKET sock, void* data, uint32_t size, sockaddr_in target_R)
{
int slen_ = sizeof(target_R);
char* ptr = static_cast<char*>(data);
while (size > 0)
{
int bytes = recvfrom(sock, ptr, static_cast<int>(size), MSG_WAITALL, (sockaddr*)&target_R, &slen_);
if (bytes < 0) return false;
ptr += bytes;
size -= bytes;
}
return true;
}
DWORD WINAPI Server_Recebe(LPVOID lpParam)
{
// Created client socket
SOCKET client = *(SOCKET*)lpParam;
sockaddr_in target_R = {};
target_R.sin_family = AF_INET;
target_R.sin_addr.s_addr = inet_addr(ip);
target_R.sin_port = htons(PORT);
// Server executes continuously
while (true)
{
uint32_t size;
if (!recvall(client, &size, sizeof(size), target_R))
{
cout << "Error while recv frame" << endl;
break;
}
std::vector<uchar> buff(size);
if (!recvall(client, buff.data(), size, target_R))
{
cout << "Error while recv frame" << endl;
break;
}
cv::Mat imgMat = cv::imdecode(Mat(buff), IMREAD_COLOR);
namedWindow("Client screen seen from the Server", WINDOW_NORMAL);
cv::imshow("Client screen seen from the Server", imgMat);
cv::waitKey(1);
}
return 1;
}
After making changes to the socket code now I get the following output:
Error while recv frame
Where is the error now?
In your UDP code, your calls to
recvfrom()andsendto()are both wrong, as you are not given either of them a validsockaddr_in. You are passing in yourSOCKEThandle where asockaddr_inis expected. A socket handle is not a socket address.recvfrom()needs a validsockaddr_in, so it can tell you where the received data was sent from.Also, the
ifstatement around yourrecvfrom()call is missing a required set of parenthesis, so theifis not even being evaluated correctly. The==comparison operator has a higher precedence than the=assignment operator, so an expression like:if (a = b() == c)is evaluated as:
if (a = (b() == c))but that is not what you want. You want this instead:
if ((a = b()) == c)so write it that way explicitly.
It needs to look more like the:
sendto()also needs a validsockaddr_in, so you can tell it where to send the data to.It should look more like this: