套接字读写不按顺序

时间:2017-12-08 05:37:16

标签: c++ sockets

我试图创建一个等待2个客户端连接的简单服务器程序,发送第一个客户端" 1"第二个" 2"告诉他们谁是第一个。那我想要这种行为:

客户端1:写入

客户端2:接收并打印

客户端2:写入

客户端1:接收并打印

我得到的是一种奇怪的行为:

客户端1:写入

客户端2:写入,只有然后获取客户端1编写的内容

客户端1:写入,只有然后获取客户端1编写的内容

它继续前进。

CLIENT

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <netdb.h>
#include <iostream>
#include <unistd.h>
using namespace std;
int main() {
    int clientSocket,first,readValue = 1;
    char buffer[1024];
    struct sockaddr_in serverAddr;
    struct in_addr address;
    struct hostent *server;
    clientSocket = socket(AF_INET, SOCK_STREAM, 0);
    if(!inet_aton("127.0.0.1", &address)){
        throw "Can't parse IP address";
    }
    server = gethostbyaddr((const void*)&address, sizeof address, AF_INET);
    if(server == NULL){
        throw "Host is unreachable";
    }
    serverAddr.sin_family = AF_INET;
    memcpy((char*)&serverAddr.sin_addr.s_addr,
            (char*)server->h_addr, server->h_length);
    serverAddr.sin_port = htons(8000);

    if(connect(clientSocket, (struct sockaddr *) &serverAddr,
        sizeof serverAddr)){
        throw "error connecting server";
    }
    cout<< "connected to server";
    //Server tells the client if he's first or second
    memset(&buffer[0], 0, sizeof(buffer));
    read(clientSocket, buffer, sizeof buffer - 1);
    //assigning the "first" variable
    if(!strcmp(buffer,"1")){
        first = 1;
        cout<<"I am first";
    }
    else if(!strcmp(buffer,"2")){
        first = 0;
        cout<<"I am first";
    }
    else{
        cout<<"Error";
        return 0;
    }
    while (true)
    {
        memset(&buffer[0], 0, sizeof(buffer));
        if(first == 0){
            //read from server
            readValue = read(clientSocket, buffer, sizeof buffer);
            if(readValue < 1){
                throw "Error reading from socket";
            }
            cout<<buffer<<endl;
            //print it
            memset(&buffer[0], 0, sizeof(buffer));
            //write to buffer
            cin>>buffer;
            write(clientSocket,buffer,sizeof buffer);
            memset(&buffer[0], 0, sizeof(buffer));
        }
        if(first == 1){
            //write to buffer
            cin>>buffer;
            write(clientSocket,buffer,sizeof buffer);
            memset(&buffer[0], 0, sizeof(buffer));
            //read from server
            readValue = read(clientSocket, buffer, sizeof buffer);
            if(readValue < 1){
                throw "Error reading from socket";
            }
            cout<<buffer<<endl;

        }
    }

    return 0;
}

SERVER

void GameServer::start(){
    int client1_sd, client2_sd;
    char buffer[1024];
    //clients' variables
    struct sockaddr_in client1Address, client2Address;
    socklen_t client1AddressLen, client2AddressLen;
    //cleaning buffer
    memset(&buffer[0], 0, sizeof(buffer));
    //Creating the socket
    serverSocket = socket(AF_INET, SOCK_STREAM, 0);
    if(serverSocket == -1){
        throw "Error opening socket";
    }
    //Creating socket address variable for binding
    struct sockaddr_in serverAddress;
    //initializing it to 0's
    bzero((void *)&serverAddress, sizeof(serverAddress));
    serverAddress.sin_family = AF_INET;
    //Gets connections from anything
    serverAddress.sin_addr.s_addr= INADDR_ANY;
    serverAddress.sin_port = htons(port);
    //binding
    if (bind(serverSocket, (struct sockaddr* )&serverAddress,
        sizeof(serverAddress)) == -1){
        throw "Error on binding";
    }
    listen(serverSocket, MAX_CONNECTED_CLIENTS);
    //If a game has ended, start a new one
    while(true){
        //start listening for clients
        cout<<"Waiting for connections"<<endl;
        //Accepting first client
        client1_sd = accept(serverSocket,
                (struct sockaddr* )&client1Address,
                 &client1AddressLen);
        cout<< "Client 1 entered!"<<endl;
        //Sending 1 to him to show him he is the first to enter
        buffer[0] = '1';
        write(client1_sd,buffer,1024);
        //Accepting second client
        client2_sd = accept(serverSocket,
                (struct sockaddr* )&client1Address,
                &client1AddressLen);
        cout<<"Client 2 entered!"<<endl;
        //Sending 2 to him to show him he is the second to enter
        buffer[0] = '2';
        write(client2_sd,buffer,1024);
        while(true){
            memset(&buffer[0], 0, sizeof(buffer));
            //taking input form client 1
            read(client1_sd, buffer, 1024);
            if(!strcmp(buffer, "End")){
                close(client1_sd);
                close(client2_sd);
                break;
            }
            cout<<buffer<<endl;
            //returning the message
            write(client2_sd, buffer, 1024);
            memset(&buffer[0], 0, sizeof(buffer));
            //taking input from client 2
            read(client2_sd, buffer, 1024);
            if(strcmp(buffer, "End") == 0){
                close(client1_sd);
                close(client2_sd);
                break;
            }
            cout<<buffer<<endl;
            //returning the message
            write(client1_sd, buffer, 1024);
        }
    }
}

1 个答案:

答案 0 :(得分:0)

虽然user4581301在其注释中确实写了什么,但是即使读写数据没有零碎,您的程序也不会表现出想要的行为,因为:

  • 服务器通过write(clienti_sd,buffer,1024)发送“ 1”和“ 2”,i。 e。它发送1024个字节;
  • 每个客户端都以read(clientSocket, buffer, sizeof buffer - 1)接收号码,即e。,因为它是char buffer[1024],所以它只能接收1023个字节;
  • 因此,客户端还有1个未读字节,第二个客户端随后用其下一个read from server接收该字节,将其误认为将是服务器从第一个客户端接收到之后发送的数据。第二个客户继续尽早写作。