#c #sockets
#c #сокеты
Вопрос:
Способ написания моего кода в настоящее время позволяет считывать сообщение с сервера только непосредственно после ввода и отправки сообщения. Однако этот код предназначен для сервера чата и должен разрешать чтение в любое время отправки сообщения.
#include <iostream>
#include <string>
#include <cstring>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#define SERVER_ADDRESS "127.0.0.1"
constexpr int server_port = 15555;
#define SERVER_SUCCESS "1"
#define SERVER_FAILURE "-1"
constexpr int msg_buffer_size = 4096;
int main(int argc, char *argv[])
{
struct sockaddr_in serv_addr;
int sock;
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
std::cerr << "Socket creation failed!" << std::endl;
return 1;
}
memset(amp;serv_addr, '0', sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(server_port);
if (inet_pton(AF_INET, SERVER_ADDRESS, amp;serv_addr.sin_addr) <= 0)
{
std::cerr << "Invalid server address!" << std::endl;
return 1;
}
if (connect(sock, (struct sockaddr*)amp;serv_addr, sizeof(serv_addr)) < 0)
{
std::cerr << "Failed to connect to chat server!" << std::endl;
return 1;
}
int valread;
while (true)
{
std::cout << ">> ";
char msg[msg_buffer_size];
char return_msg[msg_buffer_size];
std::string input;
std::getline(std::cin, input);
if (input == "quit")
return 0;
if (input.length() > 4000)
{
std::cout << "Input length must be less than 4000 characters." << std::endl;
continue;
}
strcpy(msg, input.c_str());
if (send(sock, msg, strlen(msg), 0) < 0)
{
std::cout << "Error sending data." << std::endl;
continue;
}
if (recv(sock, return_msg, msg_buffer_size, 0) < 0)
{
std::cout << "Error receiving data." << std::endl;
continue;
}
std::string code(strtok(return_msg, " "));
if (code == SERVER_FAILURE)
std::cout << "Failure: " << strtok(NULL, "") << std::endl;
else
std::cout << strtok(NULL, "") << std::endl;
memset(msg, 0, msg_buffer_size);
memset(return_msg, 0, msg_buffer_size);
}
std::cout << "Exiting." << std::endl;
close(sock);
return 0;
}
Каков был бы правильный способ разрешить клиенту получать сообщение, как только оно отправляется с сервера? Я думал о создании потока, но это казалось излишним, поскольку я получал бы в двух местах.
Комментарии:
1. Знакомы ли вы с
poll()
select()
системными вызовами or? Если вы этого не сделаете, пришло время найти хорошую книгу и узнать, как они работают. Они не могут быть полностью объяснены в одном или двух кратких абзацах stackoverflow.com . Вам нужно выучить их формально. Если вы знаете, как они работают, каков ваш конкретный вопрос о том, как их использовать для выполнения этой задачи?2. Я не знал ни об одном из этих системных вызовов. Я впервые работаю с сокетами на C . Спасибо вам за предложение, я рассмотрю их.
3. Также посмотрите на темы.
4. Потоки интересны, но их не следует использовать в модели «поток на соединение» (если только это не игрушечный проект или что-то из 80-х). В Linux see
epoll
и BSD seekqueue
— оба работают значительно лучше при более высоких нагрузках. Я не программировал Windows / Solaris, но у них обоих есть так называемые порты завершения, которые подходят для более высоких нагрузок.