Socket Operation on non-socket

Asked

Viewed 382 times

1

I’m learning to program sockets but I’m having problems when it comes to exchanging messages between the client and the server, the two codes work as "should" only the problem is time to send a message and receive.

cpp client.

#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <iostream>
#include <errno.h>

struct sockaddr_in server;

#define buffer 200

int main(){

    std::string menssagm;

    int clientfd=(socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));

    if(clientfd==-1){
        perror("socket");
        std::cout << "Falha\n";
    }else{
        std::cout << "Ok...\n";
    }

    server.sin_family=AF_INET;
    server.sin_port=htons(2000);
    server.sin_addr.s_addr=inet_addr("127.0.0.1");

    int serverfd=(connect(clientfd, (struct sockaddr*)&server, sizeof(server)));

    if(serverfd==-1){
        std::cout << "Erro...\n";
        perror("connect");
    }else{
        std::cout << "Conexão estabelecida com sucesso\n";

        if((recv(serverfd,(void*)menssagm.c_str(), buffer, 0)==-1)){
            std::cout << "Erro ao receber menssagem\n";
            perror("recv");
        }else{
            std::cout << "Menssagem recebida\n";
            std::cout << menssagm << "\n";
        }

        if((send(serverfd, "script kiddie", buffer, 0)==-1)){
            std::cout << "Erro ao enviar menssagem\n";
            perror("send");
        }else{
            std::cout << "Menssagem enviada";
        }

    }
}

cpp server.

#include <iostream>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>

struct sockaddr_in local;
struct sockaddr_in remoto;

std::string hello="Hello";
std::string word;

int main(){

    int localFd=((socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)));

    local.sin_family=AF_INET;
    local.sin_port=htons(2000);
    local.sin_addr.s_addr = inet_addr("127.0.0.1");

    bind(localFd,(struct sockaddr*)&local, sizeof(local));

    listen(localFd,1);

    int remotoFd;
    socklen_t len=sizeof(remoto);

    if((remotoFd=accept(localFd, (struct sockaddr*)&remoto, &len))==-1){
        std::cout << "Erro...\n";
    }else{
        std::cout << "Conexão recebida com sucesso\n";
        send(remotoFd, hello.c_str(), 50, 0);
        recv(remotoFd, (void*)word.c_str(), 50, 0);

        std::cout << word << "\n";
    }
}

The return of function perror is:

recv(): Socket operation on non-socket
send(): Socket operation on non-socket

1 answer

2


Your mistake lies in thinking that connect() returns a descriptor. The return of connect() only indicates if there has been error (-1) or success (0).

Hence the calls from send() and recv() of your client, do not use the server descriptor.

Another crucial point in your code is the manipulation of buffers read by send() and recorded by recv(), you can’t fill a std::string from the constant pointer returned by the method c_str(), he is qualified as const and its content cannot be modified in this way!

Your code block that has the call to accept() your client would look something like this:

if(accept(localFd, (struct sockaddr*)&remoto, &len)==-1)
{
    std::cout << "Erro...\n";
}
else
{
    std::cout << "Conexão recebida com sucesso\n";

    send(localFd, hello.c_str(), hello.length(), 0);

    char buf[50];
    int n = recv(localFd, (void*)buf, sizeof(buf), 0);
    buf[n] = '\0';

    std::cout << buf << "\n";
}

Here is a simple (tested) example of a client/server using the same concepts as your question:

Client:

#include <cstdio>
#include <iostream>
#include <cerrno>
#include <cstring>

#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>

#define buffer 200

int main( int argc, char * argv[] ){

    struct sockaddr_in srv;

    int s = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP );

    if( s < 0 ) {
        std::cerr << "[ERRO] socket(): " << std::strerror(errno) << std::endl;
        return 1;
    }

    srv.sin_family = AF_INET;
    srv.sin_port = htons(2000);
    srv.sin_addr.s_addr = inet_addr("127.0.0.1");

    std::memset( srv.sin_zero, 0, sizeof(srv.sin_zero) );

    if(connect( s, (struct sockaddr*) &srv, sizeof(srv)) != 0){
        std::cerr << "[ERRO] connect(): " << std::strerror(errno) << std::endl;
        return 1;
    }

    std::cout << "[STATUS] Conexão estabelecida com sucesso..." << std::endl;

    if(send( s, argv[1], strlen(argv[1]), 0 ) < 0){
        std::cerr << "[ERRO] send(): " << std::strerror(errno) << std::endl;
        return 1;
    }

    std::cout << "[STATUS] Mensagem enviada com sucesso!" << std::endl;

    shutdown(s, SHUT_RDWR);
    close(s);

    return 0;
}

Server:

#include <cstdio>
#include <iostream>
#include <cerrno>
#include <cstring>

#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>

int main(void ){

    struct sockaddr_in local;
    char buf[256];

    int s = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );

    if( s < 0 ) {
        std::cerr << "[ERRO] socket(): " << std::strerror(errno) << std::endl;
        return 1;
    }

    local.sin_family = AF_INET;
    local.sin_port = htons(2000);
    local.sin_addr.s_addr = inet_addr("127.0.0.1");

    std::memset( local.sin_zero, 0, sizeof(local.sin_zero) );

    if(bind( s,(struct sockaddr*)&local, sizeof(local)) != 0 ) {
        std::cerr << "[ERRO] bind(): " << std::strerror(errno) << std::endl;
        return 1;
    }

    if(listen( s, 1 ) != 0){
        std::cerr << "[ERRO] listen(): " << std::strerror(errno) << std::endl;
        return 1;
    }

    while(1)
    {
        struct sockaddr_in remoto;
        socklen_t len = sizeof(remoto);

        std::cout << "[STATUS] Servidor aguardando clientes..." << std::endl;

        int client = accept( s, (struct sockaddr*) &remoto, &len );

        if( client < 0){
            std::cerr << "[ERRO] accept(): " << std::strerror(errno) << std::endl;
            return 1;
        }

        std::cout << "[STATUS] Nova conexão aceita com sucesso..." << std::endl;

        int n = recv( client, (void*)buf, sizeof(buf), 0 );

        if( n < 0 ){
            std::cerr << "[ERRO] recv(): " << std::strerror(errno) << std::endl;
            return 1;
        }

        buf[n] = '\0';

        std::cout << "[STATUS] Mensagem recebida (bytes: " << n << "): " << buf << std::endl;

        shutdown( client, SHUT_RDWR );
        close(client);
    }

    return 0;
}

Test Client:

$ ./client "Um pequeno jabuti xereta viu dez cegonhas felizes."
[STATUS] Conexão estabelecida com sucesso...
[STATUS] Mensagem enviada com sucesso!

$ ./client "The quick brown fox jumps over the lazy dog"
[STATUS] Conexão estabelecida com sucesso...
[STATUS] Mensagem enviada com sucesso!

./client "O rato roeu a roupa do rei de Roma."
[STATUS] Conexão estabelecida com sucesso...
[STATUS] Mensagem enviada com sucesso!

Server Test:

$ ./server
[STATUS] Servidor aguardando clientes...
[STATUS] Nova conexão aceita com sucesso...
[STATUS] Mensagem recebida (bytes: 50): Um pequeno jabuti xereta viu dez cegonhas felizes.
[STATUS] Servidor aguardando clientes...
[STATUS] Nova conexão aceita com sucesso...
[STATUS] Mensagem recebida (bytes: 43): The quick brown fox jumps over the lazy dog
[STATUS] Servidor aguardando clientes...
[STATUS] Nova conexão aceita com sucesso...
[STATUS] Mensagem recebida (bytes: 35): O rato roeu a roupa do rei de Roma.
[STATUS] Servidor aguardando clientes...
  • Because you gave close(...) and shutdown(..) only in the client descriptor?

  • @Khyser: Experimentally, the server code is inside an infinite loop while(1){}. The server code will NEVER reach the return 0 of main(), if there was a close() and a shutdown() there, they also would never be hit.

  • What is the difference between shutdown and close?

  • shutdown() changes the state of socket, blocking the sending and/or receiving of data in all processes that share it, however, it does not free the memory allocated by the descriptor. Already close() blocks the sending and receiving of data and releases the memory allocated by the descriptor only of the process responsible for the call. - https://stackoverflow.com/questions/4160347/close-vs-shutdown-socket

Browser other questions tagged

You are not signed in. Login or sign up in order to post.