【问题标题】:sendto api in udp for linux operating system?linux操作系统的udp中的sendto api?
【发布时间】:2014-02-24 11:47:43
【问题描述】:
int acceptSocket;
char buf[100];
long sentbytes;
socklen_t len;
int port = 18227;

int CreateSocket()
{
    long rc;
    struct sockaddr_in addr, client;

       // Socket creation for UDP
       acceptSocket=socket(AF_INET,SOCK_DGRAM,0);

       if(acceptSocket==-1)
       {
         printf("Failure: socket creation is failed, failure code\n");
         return 1;
       }
       else
       {
         printf("Socket started!\n");
       }

     memset(&addr, 0, sizeof(struct sockaddr_in));
     addr.sin_family=AF_INET;
     addr.sin_port=htons(port);
     addr.sin_addr.s_addr=htonl(INADDR_ANY);
     rc=bind(acceptSocket,(struct sockaddr*)&addr,sizeof(addr));

     if(rc== -1)
     {
       printf("Failure: listen, failure code:\n");
       return 1;
     }
     else
     {
       printf("Socket an port %d \n",port);
     }

     while(rc!=-1)
         {
         len =sizeof(client);
         rc=recvfrom(acceptSocket,buf, sizeof(buf), 0, (struct sockaddr*) &client, &len);
         if(rc==0)
         {
           printf("Server has no connection..\n");
           break;
         }
         if(rc==-1)
         {
             printf("something went wrong with data %s", strerror(errno));
           break;
         }

         XcpIp_RxCallback( (uint16) rc, (uint8*) buf, (uint16) port );

            makeTimer("First Timer", &firstTimerID, 2, 2);   //2ms
                makeTimer("Second Timer", &secondTimerID, 10, 10);    //10ms
                makeTimer("Third Timer", &thirdTimerID, 100, 100);  //100ms
          }

       close(acceptSocket);
       return 0;
     }

int main()
{
     Xcp_Initialize();
     CreateSocket();
     return 0;
}

//API for sending the data to the client.
void XcpApp_IpTransmit( uint16 XcpPort,  Xcp_StatePtr8 pBytes, uint16 numBytes )
{
    struct sockaddr_in client;

        if ((long)XcpPort==port){
                sentbytes = sendto(acceptSocket,(char*)pBytes,(long)numBytes,0, (struct sockaddr*)&client, sizeof(client));
        }
        XcpIp_TxCallback(port,(uint16)sentbytes);
}

我创建了一个服务器端程序,用于从客户端接收数据并将响应发送回客户端。我可以通过 recvfrom api 从客户端接收数据,但稍后我必须通过 XcpApp_IpTransmit( uint16 XcpPort, Xcp_StatePtr8 pBytes, uint16 numBytes ) 中的 sendto api 将响应发送回客户端; (这是我的项目中支持的用于传输数据的 api)。客户端是一个将数据发送到指定端口和ip地址的工具。我可以再次使用 struct sockaddr_in 客户端吗?在传输 api 中?有人可以帮我吗??

【问题讨论】:

    标签: c linux api sockets udp


    【解决方案1】:

    struct sockaddr_in client;是你在传输API中使用的,它在初始化的地方是错误的?

    所以你必须使用初始化套接字结构。从您上面的代码中,您可以从客户端成功接收数据但无法发送,因为您在传输函数中的client 结构是NULL 没有初始化所以去哪里?

    你可以这样做

    rc=recvfrom(acceptSocket,buf, sizeof(buf), 0, (struct sockaddr*) &client, &len);
    
    sendto(acceptSocket,buf,rc,0,(struct sockaddr *)&client,sizeof(client));
    

    或将client 结构传递给您的传输函数,如下所示

    void XcpApp_IpTransmit( uint16 XcpPort,  Xcp_StatePtr8 pBytes, uint16 numBytes,struct sockaddr* client )
    {
            if ((long)XcpPort==port){
                    sentbytes = sendto(acceptSocket,(char*)pBytes,(long)numBytes,0, (struct sockaddr*)&client, sizeof(client));
            }
            XcpIp_TxCallback(port,(uint16)sentbytes);
    }
    

    【讨论】:

    • struct sockaddr_in 客户端; // 这是在 XcpApp_IpTransmit () api 中初始化的。我无法在 XcpApp_IpTransmit api 中添加或修改参数。
    • 如果我将其作为全局变量 struct sockaddr_in 客户端,我可以在 sendto 和 recvfrom api 中使用相同的吗??
    • @user3345539 ​​在传输 API 中您刚刚声明 client 没有初始化它,您的初始化在 CreateSocket API 中完成。因此您可以将它全局化并在发送和接收 API 中使用它或通过引用client发送API。
    【解决方案2】:

    这应该有效。当您使用SOCK_DGRAM 时,您始终可以使用接收到的地址(以及它的大小,一般情况下)发回数据。当然,例外情况包括对等套接字不可用的情况。

    或者,如果您只有一个客户端,您可以使用connect 设置默认远程对等地址,send 将使用它:

    sockaddr_in addr;
    socklen_t len;
    
    len = sizeof(addr);
    x = recvfrom(socket,buf, sizeof(buf), 0, (struct sockaddr*) &addr, &len);
    connect(socket, (struct sockaddr*)addr, len);
    ...
    send(socket, buf, bufsize, 0);
    send(socket, buf, bufsize, 0);
    send(socket, buf, bufsize, 0);
    

    不过,有一条评论。您正在使用 AF_INET 并且您的代码将正常工作。但是您也可以使其与其他协议兼容。为此:

    sockadd_storage addr;
    socklen_t len;
    
    len = sizeof(addr);
    x = recvfrom(socket,buf, sizeof(buf), 0, (struct sockaddr*) &addr, &len);
    ...
    sendto(socket,buf,bufsize,0,(struct sockaddr*)addr, len);
    

    这种类型的代码适用于任何数据报协议,包括 AF_LOCAL 和 AF_INET6。

    【讨论】:

    • 我可以用 send 代替 sendto 吗??
    • @user3345539 ​​如果你使用了connect,那就是
    • sendto api 中只有 5 个参数。是这样吗?
    • 我正在使用 AF_INET 。它适用于 IPV4。我可以使用上面的代码(第二个代码)吗??
    • @user3345539 ​​取决于您的需要。如果您的服务器在严格的单线程请求-响应模式下工作,您可以使用connect。在所有其他情况下,您必须使用sendto
    猜你喜欢
    • 1970-01-01
    • 2020-09-12
    • 1970-01-01
    • 2014-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-06
    相关资源
    最近更新 更多