Я пишу чат-сервер на с ++ для собственного удовольствия, но я довольно плохо знаком с сетью в целом. Мои знания получены из руководства Биджа этого сайта и подхода сверху вниз от Kurose & Ross.
Моя проблема в том, что я написал код, похожий на тот, который вы можете найти по ссылке, но он не работает. Программа не работает, когда я пытаюсь использовать функцию recv () на сервере.
Я знаю, что recv () может вернуть любое количество байтов, но это просто дает мне -1. Я знаю, что мне нужен цикл, чтобы собрать воедино отправляемое сообщение, но пока ничего такого нет. Однако send () в клиенте говорит, что отправил сумму, указанную в буфере (да, я знаю, что это, вероятно, избыточно, хотя и не уверен, что это ошибка).
Мне кажется, что сервер ... как-то закрыт? Я почти уверен, что где-то напутал, есть определенная строка кода, в которой я действительно не уверен (см. Комментарий). Мне удалось заставить его работать вчера, но после этого что-то пошло не так.
Я действительно новичок в программировании сокетов и любых видах сетей в целом, но вызовы функций и тому подобное взяты из руководств, у меня есть догадка, проблема будет в той части, где я указываю порты и адреса, может быть, байты не приходят на сервер, потому что я отправляю их куда-то еще? Но если accept () работает, разве это не означает, что TCP-соединение сформировано, разве я не смогу использовать его после этого?
Я использую Lubuntu linux, последний выпуск, если это поможет.
Если вы обнаружите проблему, подскажите, пожалуйста, как это правильно сделать? В любом случае, вот код сервера:
void start() {
char message[1024] = "";
int socketfd = socket( AF_INET, SOCK_STREAM, 0 ), opt = 1, new_socket;
struct sockaddr_in address;
struct sockaddr_storage cl_addr;
socklen_t len = sizeof(address);
if( socketfd != 0 ) {
address.sin_family = AF_INET;
address.sin_port = htons( PORT );
address.sin_addr.s_addr = INADDR_ANY;
if( setsockopt(socketfd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(int)) < 0 ) {
perror("Setsockopt failed");
exit(EXIT_FAILURE);
}
if( bind( socketfd, (struct sockaddr*)&address, len ) < 0 ) {
perror("Couldn't bind to port");
exit(EXIT_FAILURE);
}
if( listen( socketfd, 3 ) < 0 ) {
perror("Listening on port failed");
exit(EXIT_FAILURE);
}
if( (new_socket = accept( socketfd, (struct sockaddr *)&cl_addr, (socklen_t*)&len ) < 0) ) {
perror("Couldn't accept request");
exit(EXIT_FAILURE);
}
/// This is where it fails
std::cout << recv( new_socket, message, 1024, 0) << std::endl;
close(new_socket);
}
else {
perror("Couldn't open socket");
exit(EXIT_FAILURE);
}
close( socketfd );
}
А теперь клиент:
int main(void) {
int sockfd;
struct sockaddr_in serv_addr;
char hello[1024] = "Hello";
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
/// I'm not sure about this !!
inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if( sockfd == 0 ) {
perror("Opening socket failed");
exit(EXIT_FAILURE);
}
if( connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) != -1 ) {
/// Says it sent 1024, but sever doesn't recieve it, what gives ?
int test = send( sockfd, hello, sizeof(hello), 0);
std::cout << test << std::endl;
}
else {
perror("Error");
exit(EXIT_FAILURE);
}
Как видите, это похоже на код, найденный по ссылке. Серверный код - это просто функция, есть другие части кода, такие как создание пользовательских файлов, но ни одна из них не используется в сетевой части, поэтому я не хотел публиковать еще 800 строк кода даром. Main () сервера - это только я, создающий объект класса сервера и вызывающий start () на нем.
Я бы хотел улучшить, где смогу, поэтому, если вы заметите что-то, что я могу сделать лучше, скажите, пожалуйста, будь то общий стиль кодирования или что-то еще. Кроме того, это мой первый вопрос здесь, и мой первый язык не английский, пожалуйста, будьте осторожны со мной :)