我想从服务器应用程序(在同一台计算机上)接收UDP数据包,并将其转发到不同端口上的UDP接收应用程序。服务器应用程序不是我的,我也没有源代码。
UDP接收应用程序是一个Java应用程序。如果我将Java应用程序直接绑定到服务器应用程序端口,则延迟非常低,但如果我将其连接到中继应用程序端口上,则延迟几乎为1秒。接收端口必须是非阻塞的。
#define rcv_length 160
fd_set fds;
int n;
struct timeval tv;
void CMClient::startUDPListener(){
CMport_number = 32200;
remoteAddrLen = sizeof(struct sockaddr_in);
if (WSAStartup(0x0101, &CMw) != 0)
{
fprintf(stderr, "Could not open Windows connection.n");
exit(0);
}
CMsd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (CMsd == INVALID_SOCKET)
{
fprintf(stderr, "Could not create socket.n");
WSACleanup();
exit(0);
}
CMserver.sin_family = AF_INET;
CMserver.sin_port = htons(CMport_number);
CMserver.sin_addr.s_addr = inet_addr("127.0.0.1");
long rc=bind(CMsd,(SOCKADDR*)&CMserver,sizeof(SOCKADDR_IN));
if(rc==SOCKET_ERROR)
{
printf("Error: bind code: %dn",WSAGetLastError());
}
}
void CMClient::updateData(UDPServer* svr, int CMnr){
FD_ZERO(&fds);
FD_SET(CMsd, &fds);
tv.tv_sec = 0;
tv.tv_usec = 1;
n = select ( CMsd, &fds, NULL, NULL, &tv ) ;
if (FD_ISSET(CMsd, &fds))
{
FD_CLR(CMsd,&fds);
char* rcvBuffer = new char[rcv_length];
long rc=recv(CMsd,rcvBuffer,rcv_length,0); //receive
if(rc!=SOCKET_ERROR)
{
rcvBuffer[0] = CMnr;
sendto(svr->sd, (char*)rcvBuffer, rcv_length, 0, (struct sockaddr*)&svr->server, sizeof(svr->server)) != (int)sizeof(rcvBuffer); //send
}
if(rcvBuffer)
delete [] rcvBuffer;
}
}
要发送到Java应用程序的UDP服务器初始化如下:
void UDPServer::startUDPServer(){
if (WSAStartup(0x0101, &w) != 0)
{
fprintf(stderr, "Could not open Windows connection.n");
exit(0);
}
sd = socket(AF_INET, SOCK_DGRAM, 0);
if (sd == INVALID_SOCKET)
{
fprintf(stderr, "Could not create socket.n");
WSACleanup();
exit(0);
}
server.sin_family = AF_INET;
server.sin_port = htons(port_number);
server.sin_addr.s_addr = inet_addr("127.0.0.1");
if (connect(sd, (struct sockaddr *)&server, sizeof(struct sockaddr_in)) == -1)
{
fprintf(stderr, "Could not connect name to socket.n");
stopUDPServer();
}
}
主要呼叫
UDPServer* udpsvr;
udpsvr = new UDPServer;
udpsvr->startUDPServer();
while(1){
CM->updateData(udpsvr, CMid);
}
如果能为我提供帮助,我将不胜感激。从Java应用程序接收到的数据是正确的,但延迟了约1秒。
谢谢,问候
不要在客户端上使用bind()
。使用connect()
。
总结,对于UDP:
服务器:
socket()
bind()
客户:
socket()
connect()
服务器代码示例:
// socket()
fd_ = socket(AF_INET, SOCK_DGRAM, 0);
if (fd_ < 0) {
throw std::runtime_error ("Client socket error");
}
// connect()
struct sockaddr_in serv_addr;
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(port);
struct in_addr addr;
inet_aton(address.c_str(), &addr);
bcopy(&addr, &serv_addr.sin_addr.s_addr, sizeof(addr));
if (connect(fd_, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0) {
::close(fd_);
throw std::runtime_error ("Client socket error");
}
客户端代码示例:
// socket()
fd_ = socket(AF_INET, SOCK_DGRAM, 0);
if (fd_ < 0) {
throw std::runtime_error ("Client socket error");
}
// connect()
struct sockaddr_in serv_addr;
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(port);
struct in_addr addr;
inet_aton(address.c_str(), &addr);
bcopy(&addr, &serv_addr.sin_addr.s_addr, sizeof(addr));
if (connect(fd_, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0) {
::close(fd_);
throw std::runtime_error ("Client socket error");
}
最后,您可能想了解一下刷新UDP缓冲区的情况。