В этом коде есть несколько открытых лазеек, которые могут привести к проблеме. Действительно ставлю на пункт 2.
1 - действительно ли connectTCP работает? Действительно ли он вернул работающий TCP-сокет. Вы можете легко закрыть эту проверку на наличие ошибок при вызове write()
вместо того, чтобы приводить их к void.
2 - если LINELEN является некоторой константой, такой как размер массива, размещение \r\n
в конце массива не очень поможет, если между пользовательским вводом и концом массива есть мусор (шансы вероятны есть некоторые 0). sizeof(buf)
- это максимально допустимое значение, не обязательно равное размеру того, что будет вводить пользователь.
3 - double \r\n
не обязательно, достаточно одного '\ n' (соглашение Unix).
4 - использование интерактивного пользовательского ввода для тестирования, как правило, не очень хорошая идея, это затрудняет отладку и тестирование кода.
5 - остерегайтесь записи в позиции n
в вашем буфере, если буфер чтения заполнен, он может находиться за концом буфера.
5 - если вы хотите больше, чем просто отправить одну команду и получить ответ, вам придется написать более сложный код, который управляет как write (), так и read (). Как предложил другой автор, хорошая идея - выбрать (вероятно, проще, чем нить). Вы также можете блокировать более чередующиеся команды, отправленные и полученные, но все это, вероятно, относится к другим вопросам.
Ниже приведен рабочий фрагмент кода (проверен на Linux с gcc), который получает ответ. Не сильно отличается от первоначального, надеюсь, это поможет вам закрыть лазейки.
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/un.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
enum {
LINELEN = 1024
};
int main(){
char buf[LINELEN];
int n = 0;
unsigned int option_len;
int allow_reuse = 1;
int sck = socket(PF_INET, SOCK_STREAM, 0);
char * ip = "www.google.com";
char * command = "GET http://www.google.com\n";
/* connect to socket */
struct sockaddr_in s;
memset(&s, 0, sizeof(struct sockaddr_in));
s.sin_family = AF_INET;
s.sin_port = htons(80);
s.sin_addr.s_addr = inet_addr(ip);
if (s.sin_addr.s_addr == INADDR_NONE) {
struct hostent *h = gethostbyname(ip);
if (!h) {
printf("DNS resolution failed for %s\n", ip);
exit(0);
}
s.sin_addr.s_addr = *((int*)(*(h->h_addr_list)));
}
connect(sck, (struct sockaddr*)&s, sizeof(s));
/* write command */
printf("Write to socket...\n");
write(sck, command, strlen(command));
/* get answer */
printf("Start reading from socket...\n");
while((n = read(sck, buf, LINELEN-1)) > 0) {
buf[n] = '\0'; /* ensure null-terminated */
fputs( buf, stdout );
}
}