用accept接收顺序数据

用accept接收顺序数据,c,sockets,networking,C,Sockets,Networking,我正在尝试在两个站点(a和B)之间建立通信。A应该向B发送多个数据(反之亦然):“多个数据”意味着我希望在一个接受会话中使用来自两个站点的send和recv。目前,我只是试图在每个连接上发送超过1个数据包。因为我不熟悉处理套接字,所以很可能我还没有完全理解套接字背后的概念。在下面的代码中,接收机成功地检索到发射机发送的第一个int,但没有检索到下面的int。你能告诉我我做错了什么吗 #include <stdio.h> #include <stdlib.h> #inclu

我正在尝试在两个站点(a和B)之间建立通信。A应该向B发送多个数据(反之亦然):“多个数据”意味着我希望在一个接受会话中使用来自两个站点的send和recv。目前,我只是试图在每个连接上发送超过1个数据包。因为我不熟悉处理套接字,所以很可能我还没有完全理解套接字背后的概念。在下面的代码中,接收机成功地检索到发射机发送的第一个int,但没有检索到下面的int。你能告诉我我做错了什么吗

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

#define DATA_TO_SEND_LENGTH 9
#define PRINT_ERRNO_EXIT(who,id) { \
        int verrno=errno; \
        printf("%s ERRNO: %d\nexit id: %d\n",who==0?"sender":"receiver",verrno,id); \
        return id; \
}

int main(){
    char* ipaddress="127.0.0.1";
    int portNumber=12345;
    int socketOptionalValue=1;
    const int dataToSend[]={1,2,3,4,5,6,7,8,9};

    if (fork()==0){
        // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
        // @@@@@@@@@@@@@@@ CHILD: HE IS THE SENDER @@@@@@@@@@@@@@@@
        // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
        int socketSenderDescriptor;
        struct sockaddr_in destinationInfos;
        struct sockaddr_in tmp;
        int i;
        // ************** CREATE AND OPEN THE SOCKET *****************

        inet_aton(ipaddress,&tmp.sin_addr);
        socketSenderDescriptor = socket(AF_INET, SOCK_STREAM, 0); // socket file descriptor
        if (socketSenderDescriptor < 0 ){
            PRINT_ERRNO_EXIT(0,1);
        }
        if (setsockopt(socketSenderDescriptor,SOL_SOCKET,SO_REUSEADDR,&socketOptionalValue,sizeof(socketOptionalValue))!=0){
            PRINT_ERRNO_EXIT(0,2);
        }
        if (setsockopt(socketSenderDescriptor,SOL_SOCKET,SO_KEEPALIVE,&socketOptionalValue,sizeof(socketOptionalValue))!=0){
            PRINT_ERRNO_EXIT(0,2);
        }
        memset(&destinationInfos,0,sizeof(destinationInfos)); //clean the structure used to store destination information
        destinationInfos.sin_family=AF_INET; //we want to use inet class
        destinationInfos.sin_addr.s_addr=tmp.sin_addr.s_addr;//Set destination IP
        destinationInfos.sin_port=htons(portNumber); //communiction port number
        //connection
        if (connect(socketSenderDescriptor,(struct sockaddr *)&(destinationInfos),sizeof(destinationInfos)) < 0){
            PRINT_ERRNO_EXIT(0,3);
        }
        // ******************* SEND DATA **********************
        sleep(1); //wait for the parent to start listening...
        for (i=0;i<DATA_TO_SEND_LENGTH;i++){
            printf("sender: i'm sending %d\n",dataToSend[i]);
            send(socketSenderDescriptor,&(dataToSend[i]),sizeof(dataToSend[i]),0);
            sleep(1);
        }
        // ******************* CLOSE SOCKET *******************
        if (close(socketSenderDescriptor)!=0){
            PRINT_ERRNO_EXIT(0,4);
        }
        printf("SENDER FINISH!\n");
        return EXIT_SUCCESS;
    }else {
        // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
        // @@@@@@@@@@@@@@@@ PARENT: HE IS THE RECEIVER @@@@@@@@@@@@
        // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
        struct sockaddr_in remoteSocketInfos;
        struct sockaddr_in localSocketInfos;
        int localSocketDescriptor;
        int sessionSocket;
        int valueReceived;
        int i=0;
        static socklen_t socksize=sizeof(struct sockaddr_in);
        // ******************* CREATE AND BIND THE SOCKET ******************
        //write inside localSocketInfos the information about our server
        memset(&localSocketInfos,0,sizeof(localSocketInfos));
        localSocketInfos.sin_family=AF_INET;
        localSocketInfos.sin_addr.s_addr=htonl(INADDR_ANY);
        localSocketInfos.sin_port= htons(portNumber);

        //create the main socket where all connection to our server will be received
        localSocketDescriptor=socket(AF_INET,SOCK_STREAM,0);
        if (localSocketDescriptor<0){
            PRINT_ERRNO_EXIT(1,1);
        }
        //On Linux, SO_REUSEADDR allows you to bind to an address unless an active connection is present
        //see https://stackoverflow.com/questions/4979425/difference-between-address-in-use-with-bind-in-windows-and-on-linux-errno
        setsockopt(localSocketDescriptor,SOL_SOCKET,SO_REUSEADDR,&socketOptionalValue,sizeof(socketOptionalValue));
        //Bind our socket to the socketDescription: this allows the machine to know the data
        //received on the port specified in the sockaddr_in should be handled by our specified socket.
        if (bind(localSocketDescriptor,(struct sockaddr*)&localSocketInfos,sizeof(struct sockaddr))!=0){
            PRINT_ERRNO_EXIT(1,2);
        }
        //tells our program to start listening the socket we have created. This will NOT block the flow of the program because
        //we are not waiting anything at all.
        if (listen(localSocketDescriptor,10)!=0){
            PRINT_ERRNO_EXIT(1,3);
        }
        // ************************ WAIT FOR CONNECTIONS ********************
        do {
            i++;
            printf("Waiting transmission on %s, port %d...\n",inet_ntoa(localSocketInfos.sin_addr),localSocketInfos.sin_port);
            sessionSocket=accept(localSocketDescriptor,(struct sockaddr*)&remoteSocketInfos,&socksize);
            if (sessionSocket<0){
                int verrno=errno;
                printf("receiver ERRNO: %d\n",verrno);
                continue;
            }
            printf("Incoming transmission from %s, port %d...\n",inet_ntoa(remoteSocketInfos.sin_addr),remoteSocketInfos.sin_port);
            recv(sessionSocket,&valueReceived,sizeof(valueReceived),0);
            printf("DATA READ! %d\n",valueReceived);
            close(sessionSocket);
        } while(i<DATA_TO_SEND_LENGTH);
        if (close(localSocketDescriptor)==0){
            PRINT_ERRNO_EXIT(1,4);
        }
        printf("RECEIVER FINISH!\n");
        return EXIT_SUCCESS;
    }
}

在接收方进程中,
accept()
只需要调用一次。由于将
accept()
放入
while
循环中,循环的第二次迭代将在
accept
上被阻止,因为没有新连接进入

一个简单的解决方法是将
accept
从循环中排除。您可以尝试以下修复,看看它是否有效。请注意,
关闭
也会在循环后移动

    // ************************ WAIT FOR CONNECTIONS ********************
    printf("Waiting transmission on %s, port %d...\n",inet_ntoa(localSocketInfos.sin_addr),localSocketInfos.sin_port);
    sessionSocket=accept(localSocketDescriptor,(struct sockaddr*)&remoteSocketInfos,&socksize);
    if (sessionSocket<0){
        int verrno=errno;
        printf("receiver ERRNO: %d\n",verrno);
        PRINT_ERRNO_EXIT(1,5);
    }
    do {
        i++;
        printf("Incoming transmission from %s, port %d...\n",inet_ntoa(remoteSocketInfos.sin_addr),remoteSocketInfos.sin_port);
        recv(sessionSocket,&valueReceived,sizeof(valueReceived),0);
        printf("DATA READ! %d\n",valueReceived);
    } while(i<DATA_TO_SEND_LENGTH);
    close(sessionSocket);
/*******************等待连接********************
printf(“在%s上等待传输,端口%d...n”,inet_ntoa(localsocketingfos.sin_addr),localsocketingfos.sin_端口);
sessionSocket=accept(localSocketDescriptor,(struct sockaddr*)和remotesocketinfo,&socksize);

如果(sessionSocketI按照您的建议进行了尝试,但接收器以这种方式从套接字读取随机数据:两个电台不同步。为了避免这种情况,我真的必须在通信中手动执行同步序列吗?我不确定如何继续。@Koldar它们应该同步。我自己尝试过,但没有看到任何同步问题。希望您已经找到正确的解决方法。
    // ************************ WAIT FOR CONNECTIONS ********************
    printf("Waiting transmission on %s, port %d...\n",inet_ntoa(localSocketInfos.sin_addr),localSocketInfos.sin_port);
    sessionSocket=accept(localSocketDescriptor,(struct sockaddr*)&remoteSocketInfos,&socksize);
    if (sessionSocket<0){
        int verrno=errno;
        printf("receiver ERRNO: %d\n",verrno);
        PRINT_ERRNO_EXIT(1,5);
    }
    do {
        i++;
        printf("Incoming transmission from %s, port %d...\n",inet_ntoa(remoteSocketInfos.sin_addr),remoteSocketInfos.sin_port);
        recv(sessionSocket,&valueReceived,sizeof(valueReceived),0);
        printf("DATA READ! %d\n",valueReceived);
    } while(i<DATA_TO_SEND_LENGTH);
    close(sessionSocket);