2016-09-13 1 views
1

Я хочу создать сокет, который может читать некоторые цифры, а не строку, чтобы я мог выполнять некоторые манипуляции с ними. Как я могу отправить целое число вместо строки Это моя текущая программа:Как передать целое число через буфер?

int main(int argc, char *argv[]) 
{ 
int sockfd, newsockfd, port, clilen; 
struct sockaddr_in serv_addr, cli_addr; 

if (argc < 2) 
error("ERROR, no port provided\n"); 
port = atoi(argv[1]); 

sockfd = socket(AF_INET, SOCK_STREAM, 0); 
if (sockfd < 0) 
error("ERROR opening socket"); 

bzero((char *) &serv_addr, sizeof(serv_addr)); 
serv_addr.sin_family = AF_INET; 
serv_addr.sin_addr.s_addr = INADDR_ANY; 
serv_addr.sin_port = htons(port); //host to network 

if (bind(sockfd, (struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0) 
error("ERROR binding to socket"); 

listen(sockfd,2); 
clilen = sizeof(cli_addr); 
newsockfd = accept(sockfd,(struct sockaddr *)&cli_addr, &clilen); 
int n; 
void* buffer[256]; 
n = read(newsockfd,buffer,255); 


if (n < 0) error("ERROR reading from socket"); 
printf("Message received:%d\n",d); 

n = write(newsockfd,buffer, strlen((char *)buffer)); 
if (n < 0) 
error("ERROR writing back to socket"); 

return 0;} 

Я попытался это:

int n= 5; 
write(newsockfd,&n, sizeof(int)); 

Но на стороне клиента (также ничтожной * буфер), Безразлично» Кажется, что-то читал. Может ли кто-нибудь помочь мне, как я могу это исправить?

Одним из решений может быть передача строк, а затем преобразование в int и т. Д. Но так ли это?

+0

для удобства чтения и понимания: 1) следовать аксиоме: * только один оператор в строке и (в большинстве) одна переменная декларация за оператор. * 2) последовательно отступать код: отступ после каждого (даже необязательного) открытия скобок '{'. unindent перед каждой (даже необязательной) закрывающей скобками '}'. – user3629249

+0

функции: 'listen()' и 'accept()' должны иметь свои возвращаемые значения, чтобы убедиться, что операция прошла успешно. – user3629249

+0

опубликованный код не компилируется. Помимо всего прочего, отсутствуют все необходимые инструкции '# include'. При задании вопроса о разнообразии: «почему мой код не работает», почтовый код, который является чисто компилируемым, является небольшим и все еще показывает проблему. – user3629249

ответ

2

Проблема состоит в два раза:

Первая проблема заключается в том, что декларация void* buffer[256] объявляет buffer быть массивом из 256 указателей на void, на самом деле не то, что предназначено я думаю. Вместо этого, если вы хотите, чтобы массив из 256 байтов делал только char buffer[256].

Вторая проблема заключается в том, что на принимающей стороне вы обрабатываете данные как строку, но это не строка, это двоичное значение данных.

Вторая проблема может быть решена двумя способами: либо вы преобразовываете целое число в строку, и отправляете эту строку. Или вы получаете необработанные данные целого числа и преобразуете его в int. Первое решение включает sprintf, а другое решение включает либо memcpy, либо указатели и литье.


Для первого решения выше, вы могли бы сделать что-то вроде этого:

char temp[32]; 
snprintf(temp, sizeof temp, "%d", n); 
write(newsockfd, temp, sizeof temp); 

На приемном конце вы читали его как строку:

char buffer[32]; 
n = read(newsockfd, buffer, sizeof buffer); 
if (n <= 0) 
{ 
    // Error or connection closed 
} 

// TODO: Since TCP is a streaming protocol, we could actually receive 
//  less than the number of bytes we asked to read, so we need 
//  to read in a loop 

// Print the received data as a string 
printf("Received '%s'\n", buffer); // Works because the sender sent with the terminator 

// Convert to integer 
int i = strtol(buffer, NULL, 10); 
printf("Received %d\n", i); 

Для второе решение выше, отправьте целочисленное значение как необработанные двоичные данные, как вы уже это сделали, но при получении этого делайте что-то вроде

char buffer[32]; 
n = read(newsockfd, buffer, sizeof buffer); 
if (n <= 0) 
{ 
    // Error or connection closed 
} 

// TODO: Since TCP is a streaming protocol, we could actually receive 
//  less than the number of bytes we asked to read, so we need 
//  to read in a loop 

int i = *(int *) buffer; 
printf("Received %d\n", i); 

Обратите внимание, что это второе решение, как написано в этом ответе, полагается, что отправитель и получатель имеют тот же endianness, а также один и тот же размер для int (который не всегда может быть дело).

Самый безопасный способ, как правило, преобразовать в строку на отправляющей стороне и получить строку как строку нужной строки. То есть первое решение.

+0

Согласитесь, что безопасный способ, как правило, преобразовывается в строку, но этот код не отправляет одну строку, а содержимое массива, которое, конечно, завершено нулем, но получающая сторона не« знает »длину массив. OTOH, если оба конца «знают», размер буфера равен 31 + 1, то почему бы «не знать» размер 'int' вместо этого - проще. Чтобы «безопасно» передавать данные, не следует зависеть от таких магических чисел, как 32. При отправке _strings_ также отправляйте конечный нулевой символ. Сначала сначала отправьте информацию о размере, а затем данные. – chux

1

Я хотел бы изменить ясный ответ Joachim Pileborg.

int value, todo = sizeof(value); 
char *p = (void*) &value; 

while ((n = read(newsockfd, p, todo)) < todo) { 
    if(n == 0) { /* handle eof and break */ } 
    if(n < 0 ) { /* handle error and break */ } 

    todo -= n; 
    p += n 
} 

if(todo == 0) { 
    printf("Received %d\n", value); 
} 

Вы знаете, сколько байтов вы получаете, поэтому нет причин читать дальше. Цикл касается случая, о котором он предупреждает: , прочитанный (2), может не читать все 4 байта (маловероятно в этом случае, но не вообще).

Вы всегда можете получить char * от void * и передать любой указатель на функцию, принимающую void *. Что вы не можете сделать, портативно, это

char buffer[32]; 
... 
int i = *(int *) buffer; 

потому что массив символов не может иметь целочисленное выравнивание. На некоторых архитектурах это провоцирует SIGBUS. Если вы читаете в массив символов, безопасный способ интерпретировать эти байты как целое число

memcpy(&i, buffer, sizeof i);