我的目标是接收客户端(server_address_ob)每10毫秒连续发送的数据报,并使用UDP套接字将此接收的数据报发送到另一台服务器(server_address_hm)。这应该是连续完成的,因为我的程序应该像server_Address_ob和server_address_hm之间的中间人一样。我在C中编写了这段代码(下面),其中一些使用select()
来自互联网代码问题:
1)收到的数据和发送的数据不相同
bsnayak@ubuntu:~/Desktop/learn$ ./ar4
Main server waiting for client to respond...
(192.168.37.1 , 1901) rcvd: 0x1ae50990
(0.0.0.0 , 0) sent: 0x1ae69030
2)为什么地址为0.0.0.0,0,尽管这里使用以下定义创建套接字
server_address_hmi.sin_port = htons(1902);
server_address_hmi.sin_addr.s_addr = inet_addr("192.168.37.134");
3)虽然程序运行但是在接收和发送一次之后,程序不再接收任何数据包或发送它们。
//Main SERVER
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/select.h>//use select() for multiplexing
#include <sys/fcntl.h> // for non-blocking
#define MAX_LENGTH 100000
#define PORT 1901
/* Select() params
* int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
* FD_SET(int fd, fd_set *set);
* FD_CLR(int fd, fd_set *set);
* FD_ISSET(int fd, fd_set *set);
* FD_ZERO(fd_set *set);
*/
void error(char *message)
{
perror(message);
exit(1);
}
int main()
{
// select parameters declared
fd_set original_socket;
fd_set original_stdin;
fd_set readfds;
fd_set writefds;
struct timeval tv;
int numfd, numfd2;
// socket parameters declared
int socket_fd_ob, socket_fd_hm;
int bytes_read, bytes_sent;
char address_length, address_length2;
char recieve_data[MAX_LENGTH];
char send_data[MAX_LENGTH];
struct sockaddr_in server_address_ob, server_address_hm, client_address;
int z = 0;
//Socket creation done separately for both OB and HM communications
if ((socket_fd_ob = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{
error("socket()");
}
if ((socket_fd_hm = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{
error("socket()");
}
fcntl(socket_fd_ob, F_SETFL, O_NONBLOCK); //set socket to non-blocking
fcntl(socket_fd_hm, F_SETFL, O_NONBLOCK); //set socket to non-blocking
// clear the set ahead of time
FD_ZERO(&original_socket);
FD_ZERO(&original_stdin);
FD_ZERO(&readfds);
FD_ZERO(&writefds);
// add our descriptors to the set (0 - stands for STDIN)
FD_SET(socket_fd_ob, &original_socket);//instead of 0 put socket_fd_ob
FD_SET(socket_fd_ob, &readfds);
FD_SET(0,&original_stdin);
FD_SET(0, &writefds);
// since we got s2 second, it's the "greater", so we use that for
// the n param in select()
numfd = socket_fd_ob + 1;
numfd2 = socket_fd_hm + 1;
// wait until either socket has data ready to be recv()d (timeout 10.5 secs)
tv.tv_sec = 1;
tv.tv_usec = 500000;
server_address_ob.sin_family = AF_INET;
server_address_ob.sin_port = htons(1901);
server_address_ob.sin_addr.s_addr = inet_addr("192.168.37.1");
bzero(&(server_address_ob.sin_zero),sizeof(server_address_ob));
server_address_hm.sin_family = AF_INET;
server_address_hm.sin_port = htons(1902);
server_address_hm.sin_addr.s_addr = inet_addr("192.168.37.134");
bzero(&(server_address_ob.sin_zero),sizeof(server_address_hm));
// Bind socket to the particular addresses
if (bind(socket_fd_ob,(struct sockaddr *)&server_address_ob, sizeof(struct sockaddr)) == -1)
{
error("bind()");
}
if (bind(socket_fd_hm,(struct sockaddr *)&server_address_hm, sizeof(struct sockaddr)) == -1)
{
error("bind()");
}
address_length = sizeof(struct sockaddr);
address_length2 = sizeof(struct sockaddr);
printf("\nMain server waiting for client to respond...\n");
fflush(stdout);
while (1)
{
readfds = original_socket;
writefds = original_stdin;//problem
int recieve = select(numfd, &readfds, &writefds,/*NULL,*/ NULL, &tv);
int sent = select(numfd2, &readfds, &writefds,/*NULL,*/ NULL, &tv);
if (recieve == -1 || sent == -1)
{
perror("select"); // error occurred in select()
}
else if (recieve == 0 || sent == 0)
{
printf("Timeout occurred! No data after 1.5 seconds.\n");
}
else
{
// one or both of the descriptors have data
if (FD_ISSET(socket_fd_ob, &readfds)) //if set to read
{
FD_CLR(socket_fd_ob, &readfds);
bytes_read = recvfrom(socket_fd_ob,recieve_data,MAX_LENGTH,0,(struct sockaddr *)&client_address, &address_length);
for (z = 0; z < bytes_read; ++z) {
FD_ISSET(socket_fd_hm, &writefds);
FD_CLR(socket_fd_hm, &writefds);
//recvfrom speech recognition client and decide what to send to HM accordingly..
send_data[bytes_read] = recieve_data[bytes_read];
//block call, will wait till client enters something, before proceeding
//send the corresponding to HM
bytes_sent = sendto(socket_fd_hm,send_data,strlen(send_data)+1,0,(struct sockaddr *)&server_address_hm, &address_length2);
fflush(stdout);
}
recieve_data[bytes_read] = '\0'; //add null to the end of the buffer
send_data[bytes_read] = '\0'; //add null to the end of the buffer
printf("\n(%s , %d) rcvd: %02x\n",inet_ntoa(client_address.sin_addr),ntohs(client_address.sin_port),recieve_data);
printf("\n(%s , %d) sent: %02x\n",inet_ntoa(server_address_hm.sin_addr),ntohs(server_address_hm.sin_port),send_data);
}
} //end else
}//end while
close (socket_fd_ob);
return 0;
}
希望能够解决我的问题。感谢您提前帮助。
答案 0 :(得分:0)
您没有正确测试select()
中的错误。您可以在其中一个中收到错误。测试应该是recieve == -1 || sent == -1
,但我无法想象你为什么要两次调用select()
,或者甚至为什么要使用两个套接字。您只需需要一个选择。试试这种方式,你可能会搞出其他一些错误。
注意:由于您创建套接字的顺序,您不能依赖第二个套接字描述符大于第一个套接字描述符。您必须测试或使用max()
。