UDP客户端发送结构体数据,调用recvfrom函数阻塞问题

1.当我们想发送一个结构体给服务端时,如果该结构体是字节对齐,那么无需考虑大小端的转换

比如:

typedef struct OpenMessage
{
    int32_t  SessionType;
    int32_t  SessionId;
    int64_t  TimeStamp;

};

OpenMessage  kmessage;给结构体赋值后,char * sendbuffer = (char *)&kmessage;

2、UDP客户端/服务器端

当我们UDP定时(2s)给服务端发送数据,服务端收到数据后将此数据再发送给客户端,客户端接收,因此客户端和服务器端都会使用sendto和recvfrom,但是客户端程序当我们在一个主线程中使用sendto和recvfrom时,会出现recvfrom被阻塞,客户端没有周到数据也无法再发送数据。

UDPServer.cpp

#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <strings.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>

int UDPServer()
{
	int sock;
	struct sockaddr_in toAddr;
	struct sockaddr_in fromAddr;

	sock = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);

	if(sock < 0)
	{
		perror("socket!");
		return -1;
	}

	memset(&fromAddr,0,sizeof(fromAddr));
	fromAddr.sin_family=AF_INET;
	fromAddr.sin_addr.s_addr=inet_addr("0.0.0.0");
	fromAddr.sin_port = htons(7861);

	if(bind(sock,(struct sockaddr*)&fromAddr,sizeof(fromAddr))<0)
	{
		perror("bind!");
		close(sock);
		return -1;
	}
       int count =0;
       int recvLen;
       unsigned int addrLen;
       char recvBuffer[1024]={0};
       while(1)
      {
	    count ++;
	    addrLen = sizeof(toAddr);   //client
	    recvLen = recvfrom(sock,recvBuffer,1024,0,(struct sockaddr*)&toAddr,&addrLen);
	   if(recvLen>0)
	  {
	    recvBuffer[recvLen]= 0;
	    printf("recv size:%2d,count = %2d\n",recvLen,count);
	  
	    int ret =0;
	   ret = sendto(sock,recvBuffer,recvLen,0,(struct sockaddr*)&toAddr,sizeof(toAddr));
	   if(ret!=recvLen)
	   {
		 perror("sendto");		
	   } 
	
	 }
	 else 
         {
           sleep(1);
	 }
     }
     close(sock);
     return 0;
}

int main(int argc, char *argv[])
{
	UDPServer();
	return 0;
}

UDPClient.cpp

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>

typedef struct message
{
	int32_t  SessionType;
	int32_t  SessionId;
	int64_t  TimeStamp;

};

int main()
{
	
    int socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
    if(socket_fd == -1)
    {
        perror("udp_socket");
        return -1;
    }

   struct sockaddr_in addr;
   addr.sin_family = AF_INET;
   addr.sin_addr.s_addr = inet_addr("192.168.154.201");
   addr.sin_port = htons(4000);  
   if (addr.sin_addr.s_addr == INADDR_NONE)
       {
           printf("Incorrect ip address!");
           close(socket_fd);
           return -1;
       }
   char buff[1024];
   int sessionId =0;
   socklen_t len = sizeof(addr);
   message sendmessages;
   while (1)
       {
  
	   sleep(2);
           sessionId ++ ;
	   sendmessages.SessionType = 1;
	   sendmessages.SessionId = sessionId;
	   sendmessages.TimeStamp = 9999;
        
	   printf("client send:%d ,%d ,%lld \n", sendmessages.SessionType, sendmessages.SessionId, sendmessages.TimeStamp);
	   char * sendbuffer = (char *)&sendmessages;
           int n;
           n = sendto(socket_fd, sendbuffer, sizeof(sendmessages), 0, (struct sockaddr *)&addr, sizeof(addr));
           if (n < 0)
           {
               perror("sendto !");
           }
           memset(buff,0,sizeof (buff));
           n = recvfrom(socket_fd, buff, 1024, 0, (struct sockaddr *)&addr, &len);
           if (n>0)
           {
                message recv;
	        memcpy(&recv, buff, sizeof(message)+1);	   
                buff[n] = 0;
                printf("client recv:%d ,%d ,%lld \n", recv.SessionType, recv.SessionId, recv.TimeStamp);
            
           }
           else 
           {
               printf("recvfrom error!\n");
              
           }
    close(socket_fd);
    return 0;
}

如果想长时间客户端和服务器端交互,那么客户端出现被阻塞情况,一直收不到数据,也没有动力再去发送数据!!!

因为网络的问题,经常丢包,也就是发了之后没有响应。这样的话,recvfrom会一直停在那里,死机了一样。

 

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值