我可以使用 TCP 协议在不同线程上发送和接收数据,如以下代码所示,如何使用 UDP 协议执行相同操作?
#include <iostream>
#include <string.h>
#include <winsock2.h>
using namespace std;
//从客户端接收数据的函数
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;
}
//向客户端发送数据的函数
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;
}
// 驱动程序代码
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();
}
}
我尝试将
SOCK_STREAM
替换为 SOCK_DGRAM
并删除 listen
调用。
现在是我尝试过的UDP代码:
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();
}
我得到这个输出:
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
我需要能够使用 UDP 端口在服务器和客户端之间发送和接收数据,在同一程序中使用一个线程进行接收,另一个线程进行发送。
在您的 UDP 代码中,对
recvfrom()
和 sendto()
的调用都是错误的,因为您没有获得有效的 sockaddr_in
。
recvfrom()
需要 sockaddr_in
来告诉您数据来自哪里。
sendto()
需要一个sockaddr_in
来告诉它将数据发送到哪里。
此外,
if
周围的 recvfrom()
缺少一组必需的括号。