Unix socket c++

Chào mọi người, em mới học viết socket trong c++, em có viết thử 1 cái server để giao tiếp với client bằng python. Em làm theo hướng dẫn trên mạng nhưng mà nó cứ bị lỗi ở bước ::recv(), mọi người xem giúp em ạ. Cảm ơn mọi người.

unix_server.h

#ifndef __UNIX_SERVER__
#define __UNIX_SERVER__

#include <sys/un.h>
#include <string>

#define DEFAULT_SOCKET "/tmp/server_.sock"
#define BACKLOG_SIZE 100
#define BUFF_LENGTH 8


class UnixServer {
private:
    struct sockaddr_un sock_addr;
    int csock_fd;
    int dsock_fd;
    char * buff; 
    static UnixServer * m_instance;

    ssize_t AppendSizeToBuffer(char* buff, int val);
    ssize_t AppendStringToBuffer(char* buff, std::string& val);

    UnixServer();
    ~UnixServer();

public:
    static UnixServer * Instance();
    bool Open();
    bool Close();

    bool HandleRecvQuery();
};

#endif //__UNIX_SERVER__

unix_server.cpp

#include <sys/socket.h>
#include <string.h>

#include "unix_server.h"
#include "logger.h"

UnixServer *
UnixServer::m_instance = NULL;

UnixServer::UnixServer() {

}

UnixServer::~UnixServer() {

}

ssize_t
UnixServer::AppendSizeToBuffer(char* buff, int val) {
    memcpy(buff, &val, sizeof(val));
    return sizeof(val);
}

ssize_t
UnixServer::AppendStringToBuffer(char* buff, std::string& val) {
    ssize_t len = AppendSizeToBuffer(buff, val.length());
    memcpy(buff + len, val.c_str(), val.length());
    return len + val.length();
}

UnixServer *
UnixServer::Instance() {
    if (m_instance == NULL) {
        m_instance = new UnixServer();
    }

    return m_instance;
}

bool
UnixServer::Open() {
    int ret;

    csock_fd = ::socket(AF_UNIX, SOCK_STREAM, 0);
    if (csock_fd < 0) {
        LogError << "socket";
        return false;
    }

    memset(&sock_addr, 0, sizeof(sock_addr));
    sock_addr.sun_family = AF_UNIX;
    strncpy(sock_addr.sun_path, DEFAULT_SOCKET, sizeof(sock_addr.sun_path) - 1);

    ret = ::bind(csock_fd, (const struct sockaddr *)& sock_addr, sizeof(sock_addr));
    if (ret < 0) {
        LogError << "bind";
        return false;
    }

    ret = ::listen(csock_fd, BACKLOG_SIZE);
    if (ret < 0) {
        LogError << "listen";
        return false;
    }

    return true;
}

bool
UnixServer::Close() {
    ::close(csock_fd);
    ::unlink(DEFAULT_SOCKET);
    return true;
}

bool
UnixServer::HandleRecvQuery() {
    dsock_fd = ::accept(csock_fd, NULL, NULL);
    if (dsock_fd < 0) {
        LogError << "accept";
        return false;
    }

    ssize_t recv_size = BUFF_LENGTH;
    int ret = ::setsockopt(dsock_fd, SOL_SOCKET, SO_RCVLOWAT, (char*)&recv_size, sizeof(recv_size));
    if (ret < 0) {
        LogError << "setsockopt";
        return false;
    }

    ret = ::recv(dsock_fd, buff, recv_size, 0);
    if (ret < 0) {
        LogError << "recv";
        return false;
    }

    if (ret < recv_size) {
        LogError << "Client closed connection before sent all data";
        return false;
    }

    char * buff_ptr = (char *)buff;
    std::string send_data = "client got result";
    ssize_t send_buff_byte = AppendStringToBuffer(buff_ptr, send_data);
    ret = ::send(dsock_fd, buff, send_buff_byte, 0);
    if (ret < 0) {
        LogError << "send";
        return false;
    }

    ::close(dsock_fd);
    return true;
}

main.cpp

#include "unix_server.h"

int main()
{
    bool ret_ok = UnixServer::Instance()->Open();
    if (ret_ok) {
        while (true) {
            ret_ok = UnixServer::Instance()->HandleRecvQuery();
            if (!ret_ok) {
                break;
            }
        }
    }

    UnixServer::Instance()->Close();

    return 0;
}

client.py

import socket
import sys
import os

DEFAULT_SOCKET = '/tmp/server_.sock'

def Main():
    sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
    print(f"connecting to {DEFAULT_SOCKET}")

    try:
        sock.connect(DEFAULT_SOCKET)
    except:
        print("Unexpected error")

    try:
        message = '{:032b}'.format(19999) + '{:032b}'.format(29999)
        print(message.encode())
        sock.sendall(message.encode())

        total_recv = 0
        recv = sock.recv(64)
        print(recv)
        expected_recv = int(float(recv))

        data = ""
        while total_recv != expected_recv:
            data += sock.recv(expected_recv - total_recv)
            total_recv += len(data)
        
        print (data)

    finally:
        sock.close()

if __name__ == '__main__':
    Main()

Lỗi cụ thể là gì? Thông báo lỗi hay dấu hiệu gì mà bạn thấy lỗi xảy ra?

3 Likes

Khi start server, sau đó chờ client đến. Sau đó start client thì log dừng lại ở chỗ hàm recv (server chỉ có 1 dòng log này):


Về phía client thì nó báo thế này:

Nhờ anh xem giúp ạ.

Biến buff mình chưa thấy khởi tạo chỗ nào hết.

3 Likes

Em chạy được rồi :))) cảm ơn anh nhiều, python còn lỗi, sửa lại tí nữa là xong. Thank you so much.

1 Like
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?