Зачем указывать один и тот же порт в sin_port как на сервере, так и на клиенте? - PullRequest
0 голосов
/ 01 ноября 2018

Я изучаю Socket-программирование на C ++. Я понимаю, что сокет должен связываться с адресом сервера, а на стороне клиента существует внутренний bind(), когда вызывается connect(). Сервер прослушивает порт, указанный в sin_port из struct sockaddr_in.

Но когда я указываю один и тот же порт для sin_port из struct sockaddr_in в клиенте, означает ли это, что и клиент, и сервер связаны с одним и тем же портом. Я надеюсь, что это часть, я иду не так.

Вот коды:

СЕРВЕР:

#include<iostream>
#include<sys/socket.h>
#include<sys/types.h>
#include<unistd.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<netdb.h>
using namespace std;
int main(){

    int sockid=socket(AF_INET,SOCK_STREAM,0);
    if(sockid<0){
        cout<<"failed socket";
    }
    struct sockaddr_in server, client;
    int cz=sizeof(client);
    server.sin_family=AF_INET;
    server.sin_port=htons(9999);
    server.sin_addr.s_addr=htonl(INADDR_ANY);

    if(bind(sockid,(struct sockaddr*)&server, sizeof(server))<0){
        cout<<"Failed binding";
        return 0;
    }
    cout<<"binded\n";

    if(listen(sockid,3)<0){//
        cout<<"\nFailed Listening";
        return 0;
    }

    int client_socket=accept(sockid,(struct sockaddr*)&client, (socklen_t*)&cz);

    if(client_socket<0){
        cout<<"Failed connecting";
        return 0;
    }
    cout<<"Connected....\n";

    char buff[1024]={0};

    cout<<"enter message: ";
    cin>>buff;
    if(send(client_socket,buff,strlen(buff),0)<0){
        cout<<"\nFailed sending\n";
        return 0;
    }
    cout<<"Message sent";




    return 0;
}

КЛИЕНТ

#include<arpa/inet.h>
#include<netdb.h>
#include<iostream>
#include<sys/socket.h>
#include<sys/types.h>
#include<unistd.h>
#include<netinet/in.h>
using namespace std;
int main(){

    int sockid=socket(AF_INET,SOCK_STREAM,0);
    if(sockid<0){
        cout<<"failed socket";
    }
    struct sockaddr_in  client;

    int cz=sizeof(client);
    client.sin_family=AF_INET;
    client.sin_port=htons(9999);
    client.sin_addr.s_addr=INADDR_ANY;




    int server_socket=connect(sockid,(struct sockaddr*)&client, sizeof(client));

    if(server_socket<0){
        cout<<"Failed connecting";
        return 0;
    }
    cout<<"Connected\n";

    char buff[250];//

    recv(sockid,buff,1024,0);
    cout<<"Received msg: "<<buff;

    return 0;
}

1 Ответ

0 голосов
/ 01 ноября 2018

Сервер должен bind к тому же порту, к которому клиент connect с. Таким образом, сервер и клиент будут общаться друг с другом. Как правило, сервер bind с общеизвестным портом и listen с. Клиент не вызывает bind, что приводит к его привязке к случайному порту. Но он вызывает connect для подключения к известному порту сервера. Сервер прослушивает, отправляет и получает через известный порт. Клиент подключается к известному порту, отправляет его и получает от него.

Кроме того, на самом деле никогда не делайте этого:

recv(sockid,buff,1024,0);
cout<<"Received msg: "<<buff;

TCP не является протоколом на основе сообщений. Функция recv при вызове через сокет TCP не получает сообщение и даже не знает, что такое сообщение. Когда вы вызываете поток operator<< и передаете его char *, как и вы, он ожидает, что char * будет указывать на правильную строку в стиле C, что не гарантируется в этом коде. Хуже того, вы проигнорировали возвращаемое значение из recv, которое является только способом узнать, сколько байтов вы получили.

Здесь есть похожая проблема:

if(send(client_socket,buff,strlen(buff),0)<0){

Вы не отправляете завершающий нулевой байт, поэтому у получателя нет возможности выяснить, где заканчивается сообщение, кроме как по факту, что вы затем закроете соединение. Это работает только в том случае, если вы хотите отправить только одно сообщение, а затем закрыть соединение без какой-либо возможности ответа. И в этом случае получатель должен продолжать звонить recv, пока не получит указание о том, что соединение было закрыто, прежде чем он считает, что получил сообщение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...