nixp.ru v3.0

23 октября 2017,
понедельник,
16:24:20 MSK

DevOps с компанией «Флант»
Jo написал 13 декабря 2007 года в 21:26 (1026 просмотров) Ведет себя неопределенно; открыл 3 темы в форуме, оставил 30 комментариев на сайте.

Здравствуйте, вот решил разобраться с сокетами.

Написал сервер (server.c):

#include

#include

#include

#include

#include

#include

#include

#define MAX_BUF_LEN 1024

#define MAX_LEN_NAME 124

int main (int argc, char * argv [])

{

int sock, client_sock, count;

char * buf, * hostname;

struct sockaddr_in addr;

struct hostent * host;

buf = (char *) malloc (MAX_BUF_LEN);

if (buf == NULL)

{

fprintf (stderr, «Problem with malloc ()\n»);

return -1;

}

sock = socket (PF_INET, SOCK_STREAM, 0);

if (sock == -1)

{

fprintf (stderr, «Problem with socket ()\n»);

return -1;

}

addr.sin_family = AF_INET;

//addr.sin_addr = * (struct in_addr*) host -> h_addr_list [0];

addr.sin_port = htons (6666);

hostname = (char *) malloc (MAX_LEN_NAME);

if (hostname == NULL)

{

fprintf (stderr, «Problem with malloc\n»);

return -1;

}

gethostname (hostname, MAX_LEN_NAME);

host = gethostbyname (hostname);

if (host == NULL)

{

fprintf (stderr, «Problem with gethostbyname()\n»);

return -1;

}

addr.sin_addr = * (struct in_addr *) host -> h_addr_list [0];

if (bind (sock, (struct sockaddr *) &addr, sizeof (addr)) == -1)

{

fprintf (stderr, «Problem with bind\n»);

return -1;

}

if (listen (sock, 10) == -1)

{

fprintf (stderr, «listen () error\n»);

return -1;

}

while ( 1 ) {

client_sock = accept (sock, NULL, NULL);

if (client_sock == -1)

{

fprintf (stderr, «Problem with accept\n»);

return -1;

}

if ((count = read (client_sock, buf, MAX_BUF_LEN-1)) == -1)

{

fprintf (stderr, «Problem with read()\n»);

return -1;

}

buf [count] = '\0\′;

printf («%s\n», buf);

close (client_sock);

if (!strcmp (buf, «exit»)) break;

}

free (buf);

close (sock);

return 0;

}

Сервер сидит на 127.0.0.1

Клиент (client.c):

#include

#include

#include

#include

#include

#define MAX_BUF_LEN 1024

int main (int argc, char * argv [])

{

int sock; char * buf;

struct sockaddr_in addr;

struct hostent * host;

if (argc < 2)

{

fprintf (stderr, «Too few arguments\n»);

return -1;

}

sock = socket (PF_INET, AF_INET, 0);

if (sock == -1)

{

fprintf (stderr, «Problem with socket()\n»);

return -1;

}

addr.sin_family = AF_INET;

host = gethostbyname (argv [1]);

if (host == NULL)

{

fprintf (stderr, «Problem with host\n»);

return -1;

}

addr.sin_addr = * (struct in_addr *) host -> h_addr_list [0];

addr.sin_port = htons (6666);

if (connect (sock, (struct sockaddr *) &addr, sizeof (addr)) == -1)

{

fprintf (stderr, «problem with connect\n»);

return -1;

}

buf = (char *) malloc (MAX_BUF_LEN);

if (buf == NULL)

{

fprintf (stderr, «Problem with malloc\n»);

return -1;

}

fgets (buf, MAX_BUF_LEN, stdin);

if (write (sock, buf, MAX_BUF_LEN) == -1)

{

fprintf (stderr, «Problem with write()\n»);

return -1;

}

close (sock);

return 0;

}

Клиент коннектится к серверу через ip адрес.

проблема в том что клиент не коннектиться, сообщения вводятся

но до сервера не доходят, либо уходят куда не надо.

$ telnet localhost 6666 Вот так все отлично

А вот:

$ telnet ip 6666 не работает

Для решения проблемы:

-- пробовал сделать чтоб сервер сидел на моем ip. Но почему то всегда

выводится ошибка с bind. адресс не присваивается. ???

-- запускал клиента в виде:

$ ./client ip_addr

В качестве ip_addr указывал свой ip, пробовал указывать и localhost.

-- файервола нет.

Заранее, спасиб.

metal

bind надо делать на IN_ADDR_ANY. Проверь точное название в man.

Jo

addr.sin_addr.s_addr = htonl (INADDR_ANY);

Если вот так, тогда telnetом можо коннектиться к ip на порт 6666.

Непонятно вот что почему первоначальная версия не верна?

hostname = (char *) malloc (MAX_LEN_NAME);

if (hostname == NULL)

{

fprintf (stderr, «Problem with malloc\n»);

return -1;

}

gethostname (hostname, MAX_LEN_NAME);

host = gethostbyname (hostname);

if (host == NULL)

{

fprintf (stderr, «Problem with gethostbyname()\n»);

return -1;

}

addr.sin_addr = * (struct in_addr *) host -> h_addr_list [0];

Посмотрел обозначение макроса INADDR_ANY

это локальный адрес. 127.0.0.1

Ну почему моей версией не выходит ???

Пробовал в клиенте поменять на это:

addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);

Все равно не коннектится.

metal

INADDR_ANY — это адрес 0.0.0.0 и ядро получив егов системном вызове знает что надо прибиндится на все сетевые интерфейсы. Если ты указываешь конкретный адрес, то биндится только на него.

Jo

Теперь ясно. Спасиб.

0×00000000

точно. посмотрел.

Я спутал с INADDR_LOOPBACK, вот у него как раз 0×7f000001, локальный.

Я переделал сервер, теперь он биндится на мой ip, работает успешно, telnet передает ему сообщение. А вот Клиент не работает, почему не ясно…

Jo

т.е клиент скорей всего коннектится к моей тачке, только сообщения не приходят…

Для решения проблемы :

Пробовал не просто писать в сокет, затем на сервере читать его,

а сделал через send и recv. Не помогает.

metal

fgets проверь на ошибку.

Jo

проверил, без изменений.

metal
Jo
проверил, без изменений.

По идеи там не верно, прочитай про fdopen.

Jo

fgets (buf, MAX_BUF_LEN, stdin);

Что в ней не так? Если ты про последний символ в buf, ясно что там enter. Переделал под scanf.

0 результат.

Я ж не в сокет ввожу, а в buf. И затем его отсылаю через send.

Аль я тебя не допонял.

Jo

во ошибка в клиенте: sock = socket (PF_INET, AF_INET, 0);

надо sock = socket (PF_INET, SOCK_STREAM, 0);

metal
Jo
fgets (buf, MAX_BUF_LEN, stdin);

Что в ней не так? Если ты про последний символ в buf, ясно что там enter.

Да нет, все в ней верно, у меня были не верные представление о типе stdin.