使用"C"进行套接字编程中的数据发送

4
我之前发布过一个问题,关于同样的事情,但是我想要有关我的代码的指导。根据其他人的建议,我尝试创建发送数据包的程序。我的最大数据包结构包括头部和负载,总共16字节。如果可能,请仔细查看发送和接收代码,并指出我哪里做错了。基本上,我的客户端一直向服务器发送数据,但它永远不会结束,而服务器也无法显示结果。
客户端:
int main(int argc, char *argv[])
{
    int sockfd, portno, n;
    struct sockaddr_in serv_addr;
    struct hostent *server;
    struct packet
    { 
        long int srcID;
        long int destID;
        long int pver;
        long int profiles;
        char length;
        long int data;
    };
    if (argc < 3) {
        fprintf(stderr,"usage: %s hostname port\n", argv[0]);
        exit(0);
    }
    portno = atoi(argv[2]); //Convert ASCII to integer
    sockfd = socket(AF_INET, SOCK_STREAM, 0); // socket file descriptor

    if (sockfd < 0) 
        error("ERROR DETECTED !!! Problem in opening socket\n");

    server = gethostbyname(argv[1]);
    if (server == NULL) {
        fprintf(stderr,"ERROR DETECTED !!!, no such server found \n");
        exit(0);
    }

    bzero((char *) &serv_addr, sizeof(serv_addr)); //clear the memory for server address

    serv_addr.sin_family = AF_INET;    
    bcopy((char *)server->h_addr, 
    (char *)&serv_addr.sin_addr.s_addr,
    server->h_length);

    serv_addr.sin_port = htons(portno);

    printf("Client 1 trying to connect with server host %s on port %d\n", argv[1], portno); 

    if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0) 
    error("ERROR in connection");

    printf("SUCCESS !!! Connection established \n");

    char buffer[128];
    struct packet *pkt = (struct packet *) buffer;
    char *payload = buffer + sizeof(struct packet);
    long int packet_size;

    printf("Started Creating packet\n");
    pkt->srcID = 0x01;
    pkt->destID = 0x02;
    pkt->pver = 0x01;
    pkt->profiles = 0x01;
    pkt->length = 128;
    pkt->data = 1; 2; 3; 4; 5; 6; 7; 8;


    if (send(sockfd,pkt,sizeof(packet_size),0) <0)
        printf ("error\n");
    else
        printf ("packet send done");
    return 0;
}

服务器:

int main(int argc, char *argv[])
{
    int sockfd, newsockfd, portno, clilen;
    struct sockaddr_in serv_addr, cli_addr;
    int n;
    char wish;

    long int SrcID;
    long int DestID;
    long int Pver;
    long int Profiles;
    long int Data;
    char Length;
    char bytes_to_receive;
    char received_bytes;
    struct packet
    { 
        long int srcID;
        long int destID;
        long int pver;
        long int profiles;
        char length;
        long int data;
    };

    if (argc < 2) {
        fprintf(stderr,"usage: %s port_number1",argv[0]);
        exit(1);
    }
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) 
        error("ERROR DETECTED !!! Problem in opening socket");

    bzero((char *) &serv_addr, sizeof(serv_addr));
    portno = atoi(argv[1]);

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    serv_addr.sin_port = htons(portno);

    if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) 
        error("ERROR DETECTED !!! There was a problem in binding");

    listen(sockfd, 10);
    clilen = sizeof(cli_addr);

    printf("Server listening on port number %d...\n", serv_addr.sin_port); 

    newsockfd = accept(sockfd,(struct sockaddr *) &cli_addr, &clilen);

    if (newsockfd < 0) 
        error("ERROR DETECTED !!! the connection request was not accepted");

    char buffer[128];
    struct packet *pkt = (struct packet *) buffer;
    char *payload = buffer + sizeof(struct packet);
    long int packet_size;

    bytes_to_receive = sizeof(pkt);
    received_bytes = 0;

    if (recv(newsockfd, pkt, sizeof(pkt), 0) < 0)
        error("ERROR DETECTED !!! There was a problem in reading the data");
    else
    { 
        do {
            received_bytes += (buffer + received_bytes, bytes_to_receive - received_bytes);
        } while (received_bytes != bytes_to_receive);

        SrcID = pkt->srcID;
        DestID = pkt->destID;
        Pver = pkt->pver ;
        Profiles = pkt->profiles;
        Length = pkt->length;
        Data = pkt->data;
        printf("Data Received from Client_1 are :\n");
        printf("Source ID: %l\n", SrcID);
        printf("Destination ID: %l\n", DestID);
        printf("profile Version: %l\n", Pver);
        printf("No of Profiles: %l\n", Profiles);
        printf("Length: %l\n", Length);
        printf("data : %l\n", Data);
    }
    if (close(newsockfd) == -1) {
        error("Error closing connection with client 1");
    }

    printf("Connection with client 1 has been closed\n");
    return 0; 
}

服务器没有显示任何输出。客户端说它已经发送了数据包。在编译服务器代码时,我看到了四个警告,称所有printf语句中的格式中都有未知的转换类型字符0xa。 我猜我在服务器端某个地方出错了,但是我无法理解“序列化”。请提供您的意见,这将非常有帮助。

你应该发送 payload 而不是 pkt,对吗? - Dylan Czenski
3个回答

11

以下是我发现的几个问题:

  1. 由于处于无限循环状态,您的客户端不断发送数据包。
  2. 您错误地传递了recv函数的len参数。目前,您传递的是sizeof(packet_size),即长整型的大小(在32位操作系统上为4字节),但您可能想使用sizeof(packet)(16字节)。
  3. 您没有检查recv函数实际读取了多少字节。对于TCP,您不能保证已经读取了结构体packet的所有16字节。因此,偶尔您可能只读取了一部分字节而导致信息不完整。以下是一些伪代码示例,演示如何正确接收整个数据包:

    bytes_to_receive = sizeof(packet)
    received_bytes = 0;
    do {
        received_bytes += recv(buffer + received_bytes, bytes_to_receive - received_bytes)
    } while (received_bytes != bytes_to_receive)
    
  4. 你在客户端和服务器中使用的结构体packet是不同的。其中一个使用了char length;,另一个使用了long int length;

  5. 我认为,在服务器中进行这种赋值pkt->srcID = SrcID;没有意义,并且应该像这样SrcID = pkt->srcID;


他也无法检测到 EOS,除非他检查 recv() 的结果是否为零。 - user207421
在采纳了您的建议后,我发现一个错误:server.c:85:5:错误:函数'recv'参数过少 /usr/include/sys/socket.h:148:16:注意:此处已声明 代码的第85行是这样的: do { received_bytes += recv(buffer + received_bytes, bytes_to_receive - received_bytes); } while (received_bytes != bytes_to_receive); - user537670
在伪代码中,recv函数的参数较少,对吧...这就是我得到的错误。这段代码应该放在哪里或需要进行哪些修改... - user537670

3
客户端持续发送的问题是因为你将其置于循环中。通过修复缩进,就能够清楚地看到发生了什么:
while (1)
{
    if (send(sockfd,pkt,sizeof(packet_size),0) <0)
        printf ("error\n");
    else
        printf ("packet send done");
}

我没有看到任何服务器端打印输出......之前有人告诉我要应用序列化,你能指导一下我的代码哪些部分不正确吗?......谢谢 - user537670

0
addr_size = sizeof serverAddr;

连接(clientSocket, (struct sockaddr *) &serverAddr, addr_size);



网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接