【问题标题】:Tracing a client-server transaction - sockets in c跟踪客户端-服务器事务 - c 中的套接字
【发布时间】:2013-06-14 11:16:42
【问题描述】:

我对套接字编程很陌生,我想模拟一个客户端-服务器事务。所以对于我的客户端发送的数据包,我声明了一个sock = socket(AF_INET, SOCK_STREAM, 0),一个SOCKADDR_IN sin,我通过bind(sock, (SOCKADDR*) &sin, sizeof(sin))绑定它们,然后,在声明一个经典的struct ip头之后,并为struct iphdr * ip分配一些内存,我终于通过ip发送数据包了

sent_packet = sendto(sock, packet, sizeof(struct iphdr) + sizeof(struct tcphdr),
                    0, (struct sockaddr *) sin, sizeof(struct sockaddr));//sent_packet is an int, I use also a TCP header struct, packet is the pointer that stores the ip and tcp data

这似乎有效。但是现在,我想跟踪发送的数据包,所以我使用服务器端文件再次声明一个sock,我声明一个SOCKADDR_IN client_sin我通过accept(sock, (SOCKADDR*)&client_sin, &recsize);接受客户端的连接,但似乎我的数据包没有收到?我使用recv(sock, buffer, 32, 0) != SOCKET_ERROR 来捕获数据包,(当然我在客户端之前启动了服务器程序)。完全错了吗?

Edit on the client side (to shorten, I didn't mention the included libraries, the `struct` `iphdr`, `tcphdr`, the `in_chksum function`, as well I didn't hydrate the tcp header, for now I just want to test)



#define PORT 23

    int sendmeifyoucan(SOCKET sock, SOCKADDR_IN * sin , int size ){

        struct iphdr * ip = (struct iphdr *)malloc(sizeof(struct iphdr *));
        struct tcphdr * tcp;
        char * packet;
        int psize=0, status = 1;
        printf("%d I am lost in the web ",status);

        packet = malloc(sizeof(struct iphdr)+ sizeof(struct tcphdr));
        memset(packet, 0, sizeof(struct iphdr) + sizeof(struct tcphdr));

        sin->sin_addr.s_addr = inet_addr("127.0.0.1");
        ip->tot_len = htons(sizeof(struct iphdr) + sizeof(struct tcphdr) + psize);
        ip->ihl = 5;
        ip->version = 4;
        ip->ttl = 255;
        ip->tos = 0;
        ip->frag_off = 0;
        ip->protocol = IPPROTO_ICMP;
        ip->saddr = sin->sin_addr.s_addr;
        ip->daddr = sin->sin_addr.s_addr;
        ip->check = in_chksum((u_short *)ip, sizeof(struct iphdr));

        status = sendto(sock, packet, sizeof(struct iphdr) + sizeof(struct tcphdr),
                        0, (struct sockaddr *) sin, sizeof(struct sockaddr));

        free(packet);

        return 0;
    }


    int main(void)
    {

        int erreur = 0;

        SOCKADDR_IN sin;
        SOCKET sock;

        SOCKADDR_IN csin;
        SOCKET csock;

        int sock_err;


        if(!erreur)
        {
            sock = socket(AF_INET, SOCK_STREAM, 0);

            if(sock != INVALID_SOCKET)
            {
                printf("La socket %d est maintenant ouverte en mode TCP/IP\n", sock);
                int size = 0;
                /* Configuration */
                sin.sin_addr.s_addr = inet_addr("127.0.0.1"); 
                sin.sin_family = AF_INET;                
                sin.sin_port = htons(PORT);
                /* Listage du port */

                    sendmeifyoucan(sock, &sin,size);

                printf("Fermeture de la socket client\n");
                closesocket(csock);
                printf("Fermeture de la socket serveur\n");
                closesocket(sock);
                printf("Fermeture du serveur terminée\n");
            }
            else
                perror("socket");

        }

        return EXIT_SUCCESS;
    }

在服务器端编辑

#define PORT 23
int main(void)
{

    int erreur = 0;
    SOCKET sock;

    SOCKADDR_IN sin;
    socklen_t recsize = sizeof(sin);
    SOCKADDR_IN csin;
    char buffer[32] = "";

    int sock_err;


    if(!erreur)
    {
        sock = socket(AF_INET, SOCK_STREAM, 0);

        if(sock != INVALID_SOCKET)
        {
            printf("La socket %d est maintenant ouverte en mode TCP/IP\n", sock);
            /* Configuration */
            csin.sin_addr.s_addr = inet_addr("127.0.0.1"); 
            csin.sin_family = AF_INET;                 
            csin.sin_port = htons(PORT);
            sock_err = bind(sock, (SOCKADDR*) &csin, sizeof(csin));

            if(sock_err != SOCKET_ERROR)
            {
                sock_err = listen(sock, 5);
                printf("Listage du port %d...\n", PORT);
            }


            if(sock_err != SOCKET_ERROR)
            {
                /* Attente pendant laquelle le client se connecte */
                printf("Patientez pendant que le client se connecte sur le port %d...\n", PORT);

                sock = accept(sock, (SOCKADDR*)&sin, &recsize);
            }

            if(recv(sock, buffer, 32, 0) != SOCKET_ERROR)
            {
                    printf("Recu : %s\n", buffer);
            }
            else
            {
                printf("Impossible de se connecter\n");
            }

            closesocket(sock);
        }
        else
            perror("socket");

    }

    return EXIT_SUCCESS;
}

【问题讨论】:

  • @nos 我已经编辑了我的帖子
  • @nos 哦,是的,我确实错过了,(顺便说一句,我在 osx 上使用 Xcode)
  • @nos 所以我编辑了我的帖子,实际上似乎函数 recv(sock, buffer, 32, 0) 从未执行过。我想,当 sendto 函数被处理时,接受的连接可以将数据传递给 recv 函数。我错过了什么吗?

标签: c sockets client-server


【解决方案1】:

您不能将sendtoSOCK_STREAM 套接字一起使用。请改用connectsendwrite

此外,您通常不会在普通套接字编程中使用 struct iphdrstruct tcphdr,它们仅用于原始 ip 数据包(哪些套接字不是)。

【讨论】:

  • 谢谢,我不知道,但是在我的客户端上,我在主函数中添加了这个 if(connect(sock, (SOCKADDR*)&sin, sizeof(sin)) != SOCKET_ERROR ){ sendmeifyoucan(sock, &sin,size);},但是好像connect(sock, (SOCKADDR*)&sin, sizeof(sin)) 等于SOCKET_ERROR,你有什么想法吗?
  • 只是为了尝试我将 SOCK_STREAM 切换到 RAW 套接字,所以在使用 sendto() (status = 48) 时我收到了一条成功的状态消息,但我仍然没有在服务器端输入...
  • 使用原始套接字不会设置适当的 TCP 连接,这不是一个选项。我建议您使用 getaddrinfo 示例代码,linux.die.net/man/3/getaddrinfo
猜你喜欢
  • 2017-05-26
  • 2011-08-22
  • 2014-03-10
  • 2015-09-07
  • 2012-06-24
  • 1970-01-01
  • 2012-05-18
  • 1970-01-01
  • 2011-11-15
相关资源
最近更新 更多