在连接的套接字上进行UDP响应
UDP respond on connected socket
所以我已经用TCP编程很长一段时间了,并决定选择UDP。我不太确定需要做些什么才能让我在WAN(或lan)上进行双向通信,lan上更容易,因为我可以打开两个端口)一旦我将信息从客户端发送到服务器,我如何在该套接字上响应UDP。有直接连接的方法吗?
(当前快速功能)
int udpsock(int port, const char* addr){
int handle = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
if (handle < 1)
return -1;
sockaddr_in address;
address.sin_family = AF_INET;
if (addr == INADDR_ANY)
address.sin_addr.s_addr = INADDR_ANY;
else
address.sin_addr.s_addr = inet_addr(addr);
address.sin_port = htons( (unsigned short) port );
if ( bind( handle, (const sockaddr*) &address, sizeof(sockaddr_in) ) < 0 )
return -1;
return handle;
}
string recvudp(int sock,const int size){
sockaddr_in SenderAddr;
int SenderAddrSize = sizeof (SenderAddr);
char buf[size];
int retsize = recvfrom(sock, buf, sizeof(buf), 0, (SOCKADDR *) & SenderAddr, &Sen derAddrSize);
if (retsize == -1){
cout << "nRecv Error : " << WSAGetLastError();
if (WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == 0){
return "";
}
return " ";
}
else if (retsize < size){
buf[retsize] = NULL;
}
return buf;
}
int sendudp(string str, string ip, unsigned short port, int sock){
sockaddr_in dest;
dest.sin_family = AF_INET;
dest.sin_addr.s_addr = inet_addr( ip.c_str() );
dest.sin_port = htons( port );
int ret = sendto(sock,str.c_str(),str.size(),0, (sockaddr*)&dest,sizeof(dest));
if (ret == -1){
cout << "nSend Error Code : " << WSAGetLastError();
}
return ret;
}
有了这个,很容易用端口xxxx制作套接字,并让合作伙伴在该端口上发送数据到客户端,第四部分是我遇到一些麻烦的地方=]
让你的sendudp
函数取一个sockaddr_in
。你从recvfrom
得到一个,然后传递给sendto
。或者,将收到的sockaddr_in
传递给connect
,然后使用send
。
我假设您发布的函数应该在客户端和服务器之间共享。为了达到这个目的,它们需要稍加修改。例如,在服务器端,recvudp
应该返回客户端地址(可能作为输出参数),因为它需要稍后发送消息给它。此外,由于客户端地址结构已经填充(在服务器端recvudp
中或在客户端手动填充),我们可以将其作为参数传递给sendudp
。
Shared.h:
#ifndef SHARED_H
#define SHARED_H
#include <winsock2.h>
#include <string>
int udpsock(int port, const char* addr);
std::string recvudp(int sock, const int size, sockaddr_in& SenderAddr, int& SenderAddrSize);
int sendudp(std::string str, sockaddr_in dest, int sock);
#endif
Shared.cpp:
#include "Includeshared.h" // path to header - you might use different one
#include <iostream>
using namespace std;
int udpsock(int port, const char* addr)
{
int handle = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
if (handle < 1)
return -1;
sockaddr_in address;
address.sin_family = AF_INET;
if (addr == INADDR_ANY)
address.sin_addr.s_addr = INADDR_ANY;
else
address.sin_addr.s_addr = inet_addr(addr);
address.sin_port = htons( (unsigned short) port );
if ( bind( handle, (const sockaddr*) &address, sizeof(sockaddr_in) ) < 0 )
return -1;
return handle;
}
// function should return sender address info (for the code the server)
string recvudp(int sock, const int size, sockaddr_in& SenderAddr, int& SenderAddrSize)
{
// TODO: use std::vector<char> here instead of char array
char* buf = 0;
buf = new char[size];
int retsize = recvfrom(sock, buf, size, 0, (sockaddr*) &SenderAddr, &SenderAddrSize);
if(retsize == -1)
{
cout << "nRecv Error : " << WSAGetLastError();
if (WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == 0)
{
return "";
}
return " ";
}
else if (retsize < size)
{
buf[retsize] = NULL;
}
string str(buf);
delete[] buf;
return str;
}
// On the client side, prepare dest like this:
// sockaddr_in dest;
// dest.sin_family = AF_INET;
// dest.sin_addr.s_addr = inet_addr(ip.c_str());
// dest.sin_port = htons(port);
int sendudp(string str, sockaddr_in dest, int sock)
{
int ret = sendto(sock,str.c_str(),str.size(),0, (sockaddr*)&dest,sizeof(dest));
if (ret == -1)
{
cout << "nSend Error Code : " << WSAGetLastError();
}
return ret;
}
服务器:main.cpp:
#include <winsock2.h>
#include <string.h>
#include <iostream>
#include "..SharedIncludeshared.h"
// Link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")
#define SERVER_PORT 27015
#define MAX_MSG 1024
using namespace std;
int main(int argc, char *argv[])
{
WSADATA wsaData;
int nResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if(nResult != NO_ERROR)
{
cout << "WSAStartup failed with error: " << nResult << endl;
return 1;
}
sock = udpsock(SERVER_PORT, "127.0.0.1");
cout << "Waiting for datagram on port: " << SERVER_PORT << endl;
while(1)
{
sockaddr_in clientAddr;
// receive message
int clientAddrLen = sizeof(clientAddr);
cout << "Received message from the client: " << recvudp(sock, MAX_MSG, clientAddr, clientAddrLen) << endl;
sendudp("Hello from server!", clientAddr, sock);
}
WSACleanup();
return 0;
}
客户:main.cpp:
#include <winsock2.h>
#include <iostream>
#include "..SharedIncludeshared.h"
using namespace std;
#define MAX_MSG 1024
// Link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")
int main(int argc, char* argv[])
{
WSADATA wsaData;
int nResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (nResult != NO_ERROR)
{
cout << "WSAStartup failed with error: " << nResult << endl;
return 1;
}
SOCKET sock = INVALID_SOCKET;
// Create a socket for sending data - it does not need to be binded like listening socket!
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(sock == INVALID_SOCKET)
{
cout << socket failed with error: " << WSAGetLastError() << endl;
WSACleanup();
return 1;
}
unsigned short Port = 27015;
sockaddr_in dest;
dest.sin_family = AF_INET;
dest.sin_addr.s_addr = inet_addr("127.0.0.1");
dest.sin_port = htons(Port);
sendudp("Hello from client!", dest, sock);
sockaddr_in RecvAddr;
int recvaddrlen = sizeof(RecvAddr);
cout << "Received message from the server: " << recvudp(sock, MAX_MSG, RecvAddr, recvaddrlen) << endl;
cout << "Closing socket..." << endl;
nResult = closesocket(sock);
if(nResult == SOCKET_ERROR)
{
cout << "closesocket failed with error: " << WSAGetLastError() << endl;
WSACleanup();
return 1;
}
WSACleanup();
return 0;
}
如果你运行客户端两次,输出是:
服务器:等待端口:27015的数据报
收到客户端的消息:客户端你好!
收到客户端的消息:客户端你好!
Received message from server: Hello from server!
关闭套接字…
UDP是无连接协议,服务器只需要在UDP端口上开始侦听,客户端可以立即发送数据(数据报),不需要建立连接(例如与connect()
/accept()
,如TCP)
相关文章:
- 从udp接收帧对于人脸识别来说太慢
- VSOMEIP-2个设备之间的通信(TCP/UDP)不工作
- 当服务中的事件被触发时,如何将响应从服务发送回客户端?
- 如何使用 Boost Asio 在 Android 上获取我的本地 udp IP 地址?
- boost::asio UDP 广播客户端仅接收"fast"数据包
- (Winsock) UDP 接收工作正常,但同一套接字的发送失败
- C++ 信号和插槽不工作:插槽不响应事件
- NodeJs 服务器充斥着 UDP 广播,不发送响应
- 如何通过UDP接收QByteArray并将其解析为位字段结构?
- 发送固定大小的 UDP 数据包
- C++关于ENUM的问题。我得到的响应比枚举列表大
- SIGSEGV on Boost UDP 套接字关闭 - tcache_get at malloc.c.
- 使用 UDP 中断 while()-循环
- 应用程序在打开的简历中捕获视频后没有响应
- 使用 cpprest (Casablanca) 返回 PDF 响应
- 如何在 2 台主机之间保持 UDP 套接字连接打开
- 具有使用 UDP 套接字字节的限制的标头
- 在 Linux 中关闭 UDP 套接字后,recv 不会返回
- echo服务器没有响应udp
- 在连接的套接字上进行UDP响应