#c #sockets
#c #сокеты
Вопрос:
Я пытаюсь отправить клиенту биты, которые он должен прочитать, затем он должен их прочитать. Но по какой-то причине он не читает сообщение, он читает только фрагменты, msgLength
.Я получаю сообщение от сервера [server]The message was sent succefully.
, и клиент может читать только то msgLength
, msg
что пусто.
клиент:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <string.h>
#include <fcntl.h>
extern int errno;
int port;
int main(int argc, char *argv[])
{
int sd;
struct sockaddr_in server;
char msg[200];
int fd;
char msgLength[200];
if (argc != 3)
{
printf("Sintax: %s <adress_server> <port>n", argv[0]);
return -1;
}
port = atoi(argv[2]);
if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("Error on socket().n");
return errno;
}
server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr(argv[1]);
server.sin_port = htons(port);
if (connect(sd, (struct sockaddr *)amp;server, sizeof(struct sockaddr)) == -1)
{
perror("[client]Erorr on connect().n");
return errno;
}
if (recv(sd, msgLength, 2,0) < 0)
{
perror("[client]Erorr on recv() from the server.n");
return errno;
}
bzero(msg,100);
if (recv(sd, msg, 22,0)<0){
perror("[client]Erorr on the second recv() from the server.n");
return errno;
}
printf("msgLength: %sn",msgLength);
printf("[client]The message recived is: %sn", msg);
close(sd);
}
сервер:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/wait.h>
#define PORT 2024
extern int errno;
int main()
{
struct sockaddr_in server; r
struct sockaddr_in from;
char msg[100];
char msgrasp[100] = " ";
int sd;
pid_t pid;
if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("[server]Erorr on the socket().n");
return errno;
}
bzero(amp;server, sizeof(server));
bzero(amp;from, sizeof(from));
server.sin_family = AF_INET;
server.sin_addr.s_addr = htonl(INADDR_ANY);
server.sin_port = htons(PORT);
int optval = 1;
setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, amp;optval, sizeof(optval));
setsockopt(sd, SOL_SOCKET, SO_REUSEPORT, amp;optval, sizeof(optval));
*/
if (bind(sd, (struct sockaddr *)amp;server, sizeof(struct sockaddr)) == -1)
{
perror("[server]Erorr on the bind().n");
return errno;
}
if (listen(sd, 5) == -1)
{
perror("[server]Erorr on listen().n");
return errno;
}
while (1)
{
int client;
int length = sizeof(from);
printf("[server]We wait on the port %d...n", PORT);
fflush(stdout);
client = accept(sd, (struct sockaddr *)amp;from, amp;length);
if (client < 0)
{
perror("[server]Erorr on accept().n");
continue;
}
switch (pid = fork())
{
case -1:
perror("fork");
exit(1);
break;
case 0:
close(sd);
bzero(msg, 100);
printf("[server]Sending the text...n");
fflush(stdout);
int fd1 = open("ToSend.txt", O_RDONLY);
char msgLength[100];
read(fd1, msgrasp, 100);
sprintf(msgLength,"%ld",strlen(msgrasp) 1);
printf("msgLength: %dn",atoi(msgLength));
if ((send(client,msgLength,sizeof(msgLength),0) amp;amp; send(client, msgrasp, atoi(msgLength),0)) <= 0)
{
perror("[server]Erorr on send() to the client.n");
continue;
}
else
printf("[server]The message was sent succefully.n");
exit(2);
default:
wait(NULL);
close(client);
break;
}
}
}
Комментарии:
1. Вызовы
send()
иrecv()
действительно должны более тщательно проверять возвращаемые значения, особенноrecv()
для получения фактического количества полученных байтов.2. Примите решение: является ли заявление об использовании сообщением об ошибке или оно информационное? Если это сообщение об ошибке, оно должно быть записано в stderr, и программа должна возвращать ненулевое значение. Если он информационный, его следует записать в стандартный вывод, и программа должна завершиться с нулевым значением. Запись сообщения в стандартный вывод и возврат -1 — это шизофрения. IMO, заявление об использовании не должно быть написано вместо правильного сообщения об ошибке, а недавнее распространение инструментов, которые выдают заявления об использовании вместо краткого сообщения об ошибке, является пародией.
3. @SteveFriedl Я проверил. Если сервер записывает n бит, recv от клиента возвращает n, но
msg
пусто4. Вы не должны использовать
strlen()
для подсчета полученных байтов; вместо этого посмотрите на возвращаемое значение изrecv()
. И почему код делает это?printf("msgLength: %dn",atoi(msgLength));
после форматирования количества в строку?5. Я сделал
int recvB=recv(sd, msg, atoi(msgLength),0)
, и я получил байты. И я делаю этоprintf("msgLength: %dn",atoi(msgLength));
только для печати, чтобы узнать, отправляет ли сервер правильную информацию
Ответ №1:
Я решил это. Проблема заключалась в том, что сервер отправлял sizeof(msgLength)
witch 100, а клиент читал только 2. Если я заменю sizeof(msgLength)
на strlen(msgLength) 1
него, он будет работать просто отлично. Спасибо всем за ваше время.