2015-11-10 3 views
0

У меня есть сервер и клиент, и я пытаюсь отправить сообщение от клиента на сервер в виде строки. Я успешно сделать это один раз, но при попытке отправить другую строку, я получаю ошибку: client: connect error :Transport endpoint is already connectedКлиент-сервер отправляет строковое сообщение C++

----- Компиляция -----

g++ server.cpp -std=c++11 -o server.x -lpthread 
    g++ client.cpp -std=c++11 -o client.x 

----- Как выполнить -----

./server.x 
    ./client.x <IP Address> 

После выполнения обоих файлов, следующие опции появятся:

---------- ---------- параметры

сервер - отправить команду на сервер выход - программы

Если вы наберете «сервер» на выход, следующие варианты будут:

----- сервера Опции команды: -----

м - отправить сообщение на сервер

server.cpp

int main() { 
    int sockid, newsd; 
    struct sockaddr_in my_addr, client_addr; 
    socklen_t clilen = sizeof(client_addr); 
    thread cmd; 

    cout << "Server creating socket.\n"; 
    if((sockid = socket(AF_INET,SOCK_STREAM,0)) < 0) { 
    cout << "Socket Error.\n"; 
    exit(0); 
    } 

    cout << "Server binding my local socket.\n"; 
    bzero((char *) &my_addr,sizeof(my_addr)); 
    my_addr.sin_family = AF_INET; 
    my_addr.sin_port = htons(MY_PORT_ID); 
    my_addr.sin_addr.s_addr = htons(INADDR_ANY); 
    if(bind(sockid ,(struct sockaddr *) &my_addr,sizeof(my_addr)) < 0) { 
    cout << "Bind error.\n"; 
    exit(0); 
    } 
    cout << "Server starting listen.\n"; 
    if(listen(sockid,5) < 0) { 
    cout << "Listen error.\n"; 
    exit(0); 
    } 
    cout << "Server running...listening for connections.\n"; 

    for(; ;) { 
    cout << "Server starting accept.\n"; 

    cout << "newd: " << newsd << endl; 
    cout << "sockid: " << sockid << endl; 
    cout << "client_addr: " << &client_addr << endl; 
    cout << "clilen: " << clilen << endl; 

    if ((newsd = accept(sockid ,(struct sockaddr *) &client_addr, &clilen)) < 0) { 
     perror("Failed to accept."); 
     exit(0); 
    } 
    cout << "newsd: " << newsd << endl; 
    cout << "Server return from accept, socket for this ftp: "<< newsd << endl; 

    // close(sockid); /* child shouldn't do an accept */ 

    thread cmd (receiveCommand, newsd); 
    //cmd.detach(); 
    //cmd.join(); 

    // close (newsd); 
    // exit(0);   /* child all done with work */ 
    } 
    // cmd.join(); 
    /* Parent continues below here */ 
    close(newsd); /* parent all done with client, only child */ 
    close(sockid); 
    return 0; 

} 

void receiveCommand(int newsd) 
{ 
    string cmd; 
    int msg_ok,fail,req,tmp; 
    char command[MAXLINE], commandSize = 0; 

    req = 0; 
    if((readn(newsd,(char *)&req,sizeof(req))) < 0) { 
    perror("Read error"); 
    exit(0); 
    } 

    req = ntohs(req); 
    cout << "Client request code is: " << req << endl; 
    if (req!=REQUESTCOMMAND) { 
    cout << "Unsupported operation. goodbye\n"; 
    /* reply to client: command not OK (code: 150) */ 
    msg_ok = COMMANDNOTSUPPORTED; 
    msg_ok = htons(msg_ok); 

    if((writen(newsd,(char *)&msg_ok,sizeof(msg_ok))) < 0) { 
     perror("Write error."); 
     exit(0); 
    } 
    exit(0); 
    } 

    /* reply to client: command OK (code: 160) */ 
    msg_ok = COMMANDSUPPORTED; 
    msg_ok = htons(msg_ok); 
    if(writen(newsd,(char *)&msg_ok,sizeof(msg_ok)) < 0) { 
    perror("Write error."); 
    exit(0); 
    } 

    fail = COMMANDOK; 
    if((commandSize = read(newsd,command,MAXLINE)) < 0) { 
    perror("Command read error."); 
    fail = BADCOMMAND ; 
    } 
    command[commandSize] = '\0'; 
    tmp = htons(fail); 
    if((writen(newsd,(char *)&tmp,sizeof(tmp))) < 0) { 
    perror("Write error"); 
    exit(0); 
    } 
    if(fail == BADCOMMAND) { 
    cout << "Server cant do command.\n"; 
    close(newsd); 
    exit(0); 
    } 
    cout << "Command is: " << command << endl; 

    if(command == "gbye"){ 
    cout << endl; 
    cout << "Client requested server to shutdown...\n"; 
    cout << "Goodbye.\n"; 
    exit(0); 
    } 
    else{ 
    cout << "Command TRANSFER COMPLETE on socket " << newsd << endl; 
    } 
    close(newsd); 
} 

/* 
    To take care of the possibility of buffer limmits in the kernel for the 
    socket being reached (which may cause read or write to return fewer characters 
    than requested), we use the following two functions */ 

int readn(int sd,char *ptr,int size) 
{ 
    int no_left,no_read; 
    no_left = size; 
    while (no_left > 0) { 
    no_read = read(sd,ptr,no_left); 
    if(no_read <0) return(no_read); 
    if (no_read == 0) break; 
    no_left -= no_read; 
    ptr += no_read; 
    } 
    return(size - no_left); 
} 

int writen(int sd,char *ptr,int size) 
{   int no_left,no_written; 
    no_left = size; 
    while (no_left > 0) { 
    no_written = write(sd,ptr,no_left); 
    if(no_written <=0) return(no_written); 
    no_left -= no_written; 
    ptr += no_written; 
    } 
    return(size - no_left); 
} 

client.cpp

int main(int argc,char *argv[]) 
{ 
    int sockid, newsd, portNum, clientportNum, serverportNum; 
    struct sockaddr_in my_addr, server_addr; 

    if(argc != 2) { 
    cout << "Error: Usage : IP-dotted-notation \n", argv[0]; 
    exit(0); 
    } 

    if((sockid = socket(AF_INET,SOCK_STREAM,0)) < 0) { 
    cout << "Client Socket Error.\n"; 
    exit(0); 
    } 

    clientportNum = 8000; 
    serverportNum = 8001; 

    cout << "Client Binding My Local Socket\n"; 
    bzero((char *) &my_addr, sizeof(my_addr)); 
    my_addr.sin_family = AF_INET; 
    my_addr.sin_addr.s_addr = htonl(INADDR_ANY); 
    my_addr.sin_port = htons(clientportNum); 

    if(bind(sockid ,(struct sockaddr *) &my_addr,sizeof(my_addr)) < 0){ 
    cout << "Client Bind Error.\n"; 
    exit(0); 
    } 

    cout << "Client Starting Connect\n"; 
    bzero((char *) &server_addr,sizeof(server_addr)); 
    server_addr.sin_family = AF_INET; 
    server_addr.sin_addr.s_addr = inet_addr(argv[1]); 
    server_addr.sin_port = htons(serverportNum); 

    while(1){ 
     string cmd_option; 
     cout << endl; 
     cout << "---------- Options ----------\n"; 
     cout << "server - send a command to the server\n"; 
     cout << "exit - exit program\n"; 
     cout << endl; 

     cout << "~: "; 
     getline(cin, cmd_option); 

     if(cmd_option == "server"){ 
     // *****Error Here***** 
     if(connect(sockid ,(struct sockaddr *) &server_addr, sizeof(server_addr)) < 0) { 
      //cout << "Client Connect Error.\n"; 
      printf("client: connect error :%s\n", strerror(errno)); 
      exit(0); 
     } 
     giveServerCommand(sockid); 
     } 
     else if(cmd_option == "exit"){ 
     cout << endl; 
     cout << "Exiting program...\n"; 
     cout << "Goodbye.\n"; 
     exit(0); 
     } 
     else{ 
     cout << "Invalid Command.\n"; 
     } 
    } 
} 
void giveServerCommand(int sockid) 
{ 

    string user_input; 

    // User Interface 
    cout << "\n-----Server Command Options:-----\n"; 
    cout << "m  - send message to server\n"; 

    cout << "\n"; 

    cout << "~: "; 
    getline(cin, user_input); 

    if (user_input == "m"){ 

     string buffer; 
     cout << "\nType a command to the server: "; 
     getline(cin, buffer); 
     cout << "You typed: " << buffer << endl; 

     int getcommand,msg,msg_2,len; 
     len = buffer.size(); 

     getcommand = htons(REQUESTCOMMAND); 
     cout << "Client sending command request to server.\n"; 

     int n = 0; 
     if(n = (writen(sockid,(char *)&getcommand,sizeof(getcommand))) < 0) { 
     cout << "Client write error: " << n << endl; 
     exit(0); 
     } 

     /* want for go-ahead from server */ 
     cout << "command: " << getcommand << endl; 
     cout << "sockid: " << sockid << endl; 
     cout << "msg: " << &msg << endl; 
     cout << "msg size: " << sizeof(msg) << endl; 

     msg = 0; 
     if((readn(sockid,(char *)&msg,sizeof(msg)))< 0) { 
     cout << "Client read error.\n"; 
     exit(0); 
     } 
     cout << "msg: " << msg << endl; 
     msg = ntohs(msg); 
     cout << "msg after ntohs: " << msg << endl; 
     if (msg==COMMANDNOTSUPPORTED) { 
     cout << "Server refused command. Goodbye...\n"; 
     cout << endl; 
     exit(0); 
     } 
     else 
     cout << "Server replied, command supported.\n"; 

     /* send command to server */ 
     cout << "Client sending command.\n"; 

     cout << "sockid: " << sockid << endl; 
     cout << "buffer: " << buffer.c_str() << endl; 
     cout << "len: " << len << endl; 

     if ((writen(sockid, (char *) buffer.c_str(),len)) < 0) { 
     cout << "Client write error.\n"; 
     exit(0); 
     } 
     /* see if server replied that command is OK */ 
     cout << "sockid: " << sockid << endl; 
     cout << "msg2: " << &msg_2 << endl; 
     cout << "msg2 size: " << sizeof(msg_2) << endl; 

     msg_2 = 0; 
     if (readn(sockid, (char *)&msg_2, sizeof(msg_2)) < 0) { 
     cout << "Client read error: %s\n", strerror(errno); 
     exit(0); 
     } 

     cout << "msg2 before ntohs: " << msg_2 << endl; 
     msg_2 = ntohs(msg_2); 
     cout << "msg2 after ntohs: " << msg_2 << endl; 

     if (msg_2 == BADCOMMAND) { 
     cout << "Server reported bad command. Goodbye...\n"; 
     exit(0); 
     } 
     else 
     cout << "Server replied, Command OK.\n"; 

     /*Command transfer ends. client terminates after closing all its sockets*/ 
     cout << "COMMAND TRANSFER COMPLETE\n"; 
    } 
    else{ 
     cout << "\nInvalid Option.\n"; 
    } 
} 

int readn(int sd, char *ptr, int size) 
{ 

    int no_left,no_read; 

    cout << "-----Within readn function------" << endl; 
    cout << "sd: " << sd << endl; 
    cout << "char ptr: " << &ptr << endl; 
    cout << "size: " << size << endl; 

    no_left = size; 
    while (no_left > 0) { 
    no_read = read(sd,ptr,no_left); 
    cout << "no_read: " << no_read << endl; 
    if(no_read <0) return(no_read); 
    if (no_read == 0) break; 
    no_left -= no_read; 
    ptr += no_read; 
    } 
    cout << "size - no_left: " << size - no_left << endl; 
    cout << "--------------------------------" << endl; 
    return(size - no_left); 
} 

int writen(int sd,char *ptr,int size) 
{ 
    /* 
    cout << "-----Within writen function------" << endl; 
    cout << "sd: " << sd << endl; 
    cout << "char ptr: " << &ptr << endl; 
    cout << "size: " << size << endl; 
    */ 
    int no_left,no_written; 
    no_left = size; 
    while (no_left > 0) { 
    no_written = write(sd,ptr,no_left); 
    //cout << "no_written: " << no_written << endl; 
    if(no_written <=0) return(no_written); 
    no_left -= no_written; 
    ptr += no_written; 
    } 
    /* 
    cout << "size - no_left: " << size - no_left << endl; 
    cout << "--------------------------------" << endl; 
    */ 
    return(size - no_left); 
} 

Ошибка: client: connect error :Transport endpoint is already connected

+1

Вы используете несколько клиентов или серверов одновременно на одном компьютере? –

+0

Только один клиент и один сервер на одном компьютере @NathanTuggy – Zach

+0

Привязка клиентского сокета до подключения не требуется и может быть плохой идеей. – user4581301

ответ

0

Ваш код клиента появляется неправильно - вы вызываете подключения() в то время как (истинный) петли без необходимости для него - как только ваш клиент подключен, он не необходимо сделать это снова до тех пор, пока соединение не будет завершено и розетка не будет закрыта.

Смежные вопросы