我在两台计算机之间实现服务器-客户机,其思想是读取从连接到PC3的输入,并将其发送到PC4以及返回方式(来自连接的从P4的输入并将其发送到PC3)。
服务器端:
client:
static void FSoEThread()
{
struct timeval time1;
uint8_t pdu_in_local[sizeof(pdu_in)];
uint8_t pdu_out_local[sizeof(pdu_out)];
uint8_t pdu_in_tmp[sizeof(pdu_in)];
uint8_t pdu_out_tmp[sizeof(pdu_out)];
FILE *fp;
fp = fopen("Log.txt", "w");//opening file.
SerialPort sp(MODEMDEVICE);
int socket_desc;
struct sockaddr_in server_addr;
unsigned int server_message[255], client_message[255];
socklen_t server_struct_length = sizeof(server_addr);
;
printf("Thread_quit\n");
while(!thread_quit){
std::vector<uint8_t> uart_in(10);
sp.Read(uart_in);
if(1){
switch(ecatGetMasterState())
{
default:
break;
case _UNKNOWN:
case _INIT:
case _PREOP:
case _SAFEOP:
break;
case eEcatState_OP:
{
{
uint8_t buf[sizeof(pdu_in)]; // In data comes from Slave
if(uart_in.size() == 10){
PD_mutex.lock();
memcpy(pdu_out,&uart_in.data()[4],sizeof(pdu_out));//out data coming from Master to the Slave
memcpy(pdu_out_local,&uart_in.data()[4],sizeof(pdu_out));
memcpy(buf,pdu_in,sizeof(pdu_in));
memcpy(pdu_in_local,pdu_in,sizeof(pdu_in));
PD_mutex.unlock();
printf("\n");
sp.Write(buf,sizeof(pdu_in));
}
}
gettimeofday(&time1,NULL);
if(memcmp(pdu_in_tmp,pdu_in_local,sizeof(pdu_in)) != 0){
memcpy(pdu_in_tmp,pdu_in_local,sizeof(pdu_in));
fprintf(fp,"[%05d.%06d]in %02x %02x %02x %02x %02x %02x\n",time1.tv_sec,time1.tv_usec,
(unsigned int)pdu_in_tmp[0],
(unsigned int)pdu_in_tmp[1],
(unsigned int)pdu_in_tmp[2],
(unsigned int)pdu_in_tmp[3],
(unsigned int)pdu_in_tmp[4],
(unsigned int)pdu_in_tmp[5]
);
unsigned int *PDU_UDP_IN = (unsigned int*)pdu_in_tmp;
// Create socket:
socket_desc = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(socket_desc < 0){
printf("Error while creating socket\n");
exit(1);
}
// Clean buffers:
memset(server_message, 0, sizeof(server_message));
memset(client_message, 0, sizeof(client_message));
// Set port and IP:
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(2000);
server_addr.sin_addr.s_addr = inet_addr("10.100.20.54");
printf("sending\n");
// Send the message to server:
if(sendto(socket_desc, PDU_UDP_IN, sizeof(PDU_UDP_IN), 0,
(struct sockaddr*)&server_addr, server_struct_length) < 0){
printf("Unable to send message\n");
exit(1);
}
printf("sendto: msg send to IPC4 :\t%x\n",*PDU_UDP_IN);
socklen_t server_struct_length = sizeof(server_addr);
//recvfrom(socket_desc, server_message, sizeof(server_message), 0,(struct sockaddr*)&server_addr, &server_struct_length);
//if(int errn_ = recvfrom(socket_desc, server_message, sizeof(server_message), 0,(struct sockaddr*)&server_addr, &server_struct_length) < 0){
//printf("Error while receiving server's msg\n");
//printf("n=%d, Errno%d\n",errn_,errno);
//exit(1);
//}
printf("Recved\n");
printf("MSG from IPC4:\t%x\n",*server_message);
close(socket_desc);
}
if(memcmp(pdu_out_tmp,pdu_out_local,sizeof(pdu_out)) != 0){
memcpy(pdu_out_tmp,pdu_out_local,sizeof(pdu_out));
fprintf(fp,"[%05d.%06d]out %02x %02x %02x %02x %02x %02x\n",time1.tv_sec,time1.tv_usec,
(unsigned int)pdu_out_tmp[0],
(unsigned int)pdu_out_tmp[1],
(unsigned int)pdu_out_tmp[2],
(unsigned int)pdu_out_tmp[3],
(unsigned int)pdu_out_tmp[4],
(unsigned int)pdu_out_tmp[5]
);
}
}
}
}
}
pthread_exit(NULL);
}这一边如果运作良好..。它可以收发..。
现在发生问题的客户端..。假设我在客户端(PC3)的这端注释/删除recvfrom,..all工作正常(服务器端recvfrom和sendto工作,我获得数据并可以发送数据),当我尝试接收数据时(再次在客户端使用recvfrom函数)数据被交换了4次,然后客户机和服务器都不再做任何事情了->,我将陷入死锁,两者都在RECVFROM中被阻塞。
static void FSoEThread()
{
struct timeval time1;
uint8_t pdu_in_local[sizeof(pdu_in)];
uint8_t pdu_out_local[sizeof(pdu_out)];
uint8_t pdu_in_tmp[sizeof(pdu_in)];
uint8_t pdu_out_tmp[sizeof(pdu_out)];
int socket_desc;
struct sockaddr_in server_addr, client_addr;
unsigned int server_message[255], client_message[255];
socklen_t client_struct_length = sizeof(client_addr);
// Clean buffers:
memset(server_message, '\0', sizeof(server_message));
memset(client_message, '\0', sizeof(client_message));
FILE *fp;
fp = fopen("Llog.txt", "w");//opening file.
long save_fd;
SerialPort sp(MODEMDEVICE);
printf("thread_quit\n");
while(!thread_quit){
std::vector<uint8_t> uart_in(10);
sp.Read(uart_in);
if(1){
switch(ecatGetMasterState())
{
default:
break;
case _UNKNOWN:
case _INIT:
case _PREOP:
case _SAFEOP:
break;
case eEcatState_OP:
{
{
uint8_t buf[sizeof(pdu_in)];
if(uart_in.size() == 10){
PD_mutex.lock();
memcpy(pdu_out,&uart_in.data()[4],sizeof(pdu_out));
memcpy(pdu_out_local,&uart_in.data()[4],sizeof(pdu_out));
memcpy(buf,pdu_in,sizeof(pdu_in));
memcpy(pdu_in_local,pdu_in,sizeof(pdu_in));
PD_mutex.unlock();
sp.Write(buf,sizeof(pdu_in));
}
}
gettimeofday(&time1,NULL);
if(memcmp(pdu_in_tmp,pdu_in_local,sizeof(pdu_in)) != 0){
memcpy(pdu_in_tmp,pdu_in_local,sizeof(pdu_in));
fprintf(fp,"[%05d.%06d]in %02x %02x %02x %02x %02x %02x\n",time1.tv_sec,time1.tv_usec,
(unsigned int)pdu_in_tmp[0],
(unsigned int)pdu_in_tmp[1],
(unsigned int)pdu_in_tmp[2],
(unsigned int)pdu_in_tmp[3],
(unsigned int)pdu_in_tmp[4],
(unsigned int)pdu_in_tmp[5]
);
unsigned int * PDU_UDP_IN = (unsigned int*)pdu_in_tmp;
printf("in \t%X\n",*PDU_UDP_IN);
// Create UDP socket:
socket_desc = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(socket_desc < 0){
printf("Error while creating socket\n");
exit(1);
}
// Set port and IP:
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(2000);
server_addr.sin_addr.s_addr = inet_addr("10.100.20.54");
// Bind to the set port and IP:
if(bind(socket_desc, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0){
exit(1);
}
//printf("Listening for incoming messages...\n\n");
// Receive client's message:
printf("Recving\n");
if (recvfrom(socket_desc, client_message, sizeof(client_message), 0,(struct sockaddr*)&client_addr, &client_struct_length) < 0){
//printf("Couldn't receive\n");
//continue;
}
printf("Received\n");
// inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
printf("msg from IPC3:\t%x\n", *client_message);
// Respond to client:
printf(" sending\n");
// strcpy(server_message, client_message);
socklen_t client_struct_length = sizeof(client_addr);
if (sendto(socket_desc, PDU_UDP_IN, sizeof(PDU_UDP_IN), 0,
(struct sockaddr*)&client_addr, client_struct_length) < 0){
printf("Can't send\n");
exit(EXIT_FAILURE);
}
printf(" sent\n");
// Close the socket:
close(socket_desc);
}
if(memcmp(pdu_out_tmp,pdu_out_local,sizeof(pdu_out)) != 0){
memcpy(pdu_out_tmp,pdu_out_local,sizeof(pdu_out));
fprintf(fp,"[%05d.%06d]out %02x %02x %02x %02x %02x %02x\n",time1.tv_sec,time1.tv_usec,
(unsigned int)pdu_out_tmp[0],
(unsigned int)pdu_out_tmp[1],
(unsigned int)pdu_out_tmp[2],
(unsigned int)pdu_out_tmp[3],
(unsigned int)pdu_out_tmp[4],
(unsigned int)pdu_out_tmp[5]
);
}
}
}
}
}
pthread_exit(NULL);
}我的问题:
我在这里做错什么了吗?
有什么办法可以更容易地解决这个问题吗?我读过关于select的文章,但我不知道当我使用两台不同线程的PC时,它是否有效
3-我尝试使用像MSG_DONTWAIT这样的标志,尝试使用setsockopt() .
有办法真正调试这种情况吗?
我真的很感激你的回答
程序是真正的big...those是UDP实现的一部分。in是用C/C++编写的,其他部分都很完美,问题只是知道如何使UDP停止阻塞。
发布于 2022-06-22 16:16:42
你似乎对UDP有很多种族条件和误解。
如果服务器向客户端发送数据报,当客户端没有套接字绑定时,数据报就会丢失。直到晚些时候才排队。在反向路径上也有同样的问题。
如果服务器和客户端套接字都处于打开状态,那么至少会有数据报排队,直到缓冲区被填满为止。这给了你一个很好的机会去阅读一条信息,以免它永远丢失。
尽管如此,在这里阻塞recvfrom仍然是一个错误。数据报可能会因为网络拥塞而丢失,而无限期挂起并不是一个好的响应。
的PC时,它是否有效
如果您不知道如何使用非阻塞的UDP来处理这个问题(或者相当合理地不想花费所需的时间),只需使用TCP,并记住设置TCP_NODELAY。
我一直在用像setsockopt()这样的标志尝试使用
尝试找到TCP/IPIllustratedVol.1的第二次拷贝,如果可能的话,旧的Stevens版本(它缺少更新的更新,但涵盖的基础很好,序列图更好的IIRC)。通过尝试和错误来理解这件事是痛苦的。
strace下运行客户端和服务器,并确保显示所有的套接字系统,并具有准确(希望是同步良好)时间戳。
https://stackoverflow.com/questions/72716562
复制相似问题