Как только вы получаете даже крошечную каплю данных, вы блокируете scanf
вместо того, чтобы пытаться получить больше данных. Либо вам необходимо поддерживать перемещение данных в обоих направлениях одновременно (ожидание ввода в scanf
и данных в recv
) одновременно, либо вам нужно быть более сообразительным при изменении направления.
Рассмотрим следующий сценарий:
- Вы звоните
ReadAndWriteSocket
.
- Ваш звонок на
recv
получает только "H", самый первый байт сообщения.
- Вы передаете это "H"
printf
, но ничего не печатается, потому что ваш стандартный вывод буферизован.
- Вы звоните
scanf
и ждете вечно, но ничего не происходит, потому что пользователь не собирается ничего набирать, пока не увидит полученное сообщение.
- Ваш код больше никогда не будет вызывать
recv
, что очень плохо, так как остальная часть полученного сообщения ожидает в буфере приема, но вы застряли в scanf
.
Если у вас есть код, который перемещает данные в двух направлениях, вы должны быть абсолютно уверены, что никогда не блокируете ожидание получения данных в одном направлении, когда ожидаемые данные поступают в другом направлении. Ваш код не имеет ничего, чтобы предотвратить это.
Обновление: Проблемы с вашим новым кодом:
void *ReadAndWriteSocket(void *entrypoint) {
char message[256];
char buffer[256];
while (1) {
if((sockStructure.n = recv(sockStructure.newsockfd, buffer, strlen(buffer), 0)) > 0) {
Что здесь происходит? Вы можете передать только строку в strlen
. Но buffer
здесь не содержит строку (она неинициализирована на первом проходе и содержит несвязанную длину на последующих проходах). Таким образом, вы передаете бессмысленное значение для длины в recv
.
for(int i = 0; i < strlen(buffer) - 1; i++) {
printf("%s", buffer[i]);
Здесь две проблемы: во-первых, buffer[i]
не является строкой, а спецификатор формата %s
предназначен для строк. Во-вторых, стандартный вывод буферизуется строкой, поэтому, если в буфере не будет строки, он не будет отображаться.
}
}
}
scanf("%s", &message);
Почему вы ждете ввода пользователя здесь? Что, если вы получили только крошечную часть сообщения и даже не получили целую строку, а значит, еще ничего не вышли? Откуда вы знаете, что следующее, что вам нужно сделать, это получить вход от пользователя и не получать остальную часть сообщения?
send(sockStructure.newsockfd, message, strlen(message), 0);
}
Если у вас есть какой-то протокол, который указывает, кто будет отправлять, когда и кто будет получать, когда и что составляет сообщение, и когда ждать ввода пользователя, вы должны написать код, который реализует этот протокол. В противном случае вы застрянете в scanf
в ожидании ввода, когда в приемном буфере сокета есть данные.