Ошибка с Socket - не читаем и не пишем

Подключаем наши девайсы к компьютеру. Обсуждаются: порты, протоколы, драйвера, языки программирования и т.д.
Ответить
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2095
Зарегистрирован: Чт апр 08, 2010 18:50:01
Откуда: Краснодар

Сообщение Кислый »

Пишу программу для управления МК с компа через RS232, но команды на комп должны приходить с сети. Начал зазбираться с сокетами. И вот загвоздка - непонятная мне ошибка:

Если мы в функции

Код: Выделить всё

void OpenSock ( int socket, byte nm_socket_msg[] )
{
    socket = connectsock ( SERVER_IP, LS_PORT, "tcp" );

    if(socket < 0)	//проверяем дескриптор сокета
		return;
	else 		//подключились
		{
		    printf("Установлено соединение с %s:%s\n", SERVER_IP, LS_PORT);
		}

// вот тут !!

}
берем и читаем или пишем сокет

Код: Выделить всё

    Read_Socket(socket, nm_socket_msg, 16);
    Write_Socket(socket, nm_socket_msg, 16);
    CloseSock(socket);
то все типтоп. а если вот так:

Код: Выделить всё

typedef unsigned char byte; // 0x00 ... 0xFF

    int net_socket;
    byte net_msg[256];

void main(void)
{
    OpenSock(net_socket, net_msg);

    Read_Socket(net_socket, net_msg, 16);
    Write_Socket(net_socket, net_msg, 16);

    CloseSock(net_socket);
}
то все!! крах и тарабах!!! трындец !!! не читаем и не пишем ( о чем сведетельствует переменная n, смотри листинг ниже )

Код: Выделить всё

void Read_Socket (int socket, byte nm_socket_msg[], int len)
{   int n;
    n = recv(socket, nm_socket_msg, len, 0);
    printf("%i\n", n);
    view_pkt(nm_socket_msg, 1);
}

void Write_Socket (int socket, byte nm_socket_msg[], int len)
{   int n;
    n = send(socket, nm_socket_msg, len, 0);
    printf("%i\n", n);
    view_pkt(nm_socket_msg, 0);
}

void CloseSock (int socket)
{
    close(socket);
    printf("%s", "Соединение разорвано \n");
}

Код: Выделить всё

//функция подключения к серверу. реализация /не моё/
int connectsock(const char *host, const char *port, const char *transport)
{
    struct hostent *phe; //указатель на запись с информацией о хосте
    struct servent *pse; //указатель на запись с информацией о службе
    struct protoent *ppe; //указатель на запись с информацией о протоколе
    struct sockaddr_in sin; //структура IP-адреса оконечной точки
    int s, type; //дескриптор сокета и тип сокета
 
    //обнуляем структуру адреса
    memset(&sin, 0, sizeof(sin));
    //указываем тип адреса (IPv4)
    sin.sin_family = AF_INET;
    //задаем порт
    sin.sin_port = htons((unsigned short)atoi(port));
    //преобразовываем имя хоста в IP-адрес, предусмотрев возможность представить его
    //в точечном десятичном формате
    if(phe = gethostbyname(host))
        memcpy(&sin.sin_addr, phe->h_addr, phe->h_length);
    //преобразовываем имя транспортного протокола в номер протокола
    if((ppe = getprotobyname(transport)) == 0)
        {
            printf("Ошибка преобразования имени транспортного протокола: %s\n", strerror(errno));   //в случае неудачи выводим сообщение ошибки
            return -1;
        }
    //используем имя протокола для определения типа сокета
    if(strcmp(transport, "udp") == 0)
        type = SOCK_DGRAM;
    else
        type = SOCK_STREAM;
    //создание сокета
    s = socket(PF_INET, type, ppe->p_proto);
    if(s < 0)
        {
            printf("Ошибка создания сокета: %s\n", strerror(errno));    //в случае неудачи выводим сообщение ошибки
            return -1;
        }
    //попытка подключить сокет
    if(connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0)
        {
            printf("Не удалось подключится к серверу: %s\n", strerror(errno));  //в случае неудачи выводим сообщение ошибки
            return -1;
        }
    //возвращаем дескриптор подключенного сокета
    return s;
}
RETI ;рети-рети интеррапт, через шины данных тракт, через память, через порт, возвращайся в главный код
@hobbyelectronics
Контактная информация:
Реклама
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2095
Зарегистрирован: Чт апр 08, 2010 18:50:01
Откуда: Краснодар

Сообщение Кислый »

ошибка понята, но я хз что с ней делать.
RETI ;рети-рети интеррапт, через шины данных тракт, через память, через порт, возвращайся в главный код
@hobbyelectronics
Контактная информация:
Реклама
Встал на лапы
Аватара пользователя
Сообщения: 130
Зарегистрирован: Пт янв 21, 2011 14:16:36
Откуда: Уфа

Сообщение _AHTOXA_ »

Кислый писал(а):

Код: Выделить всё

void OpenSock ( int socket, byte nm_socket_msg[] )
{
    socket = connectsock ( SERVER_IP, LS_PORT, "tcp" );

    if(socket < 0)	//проверяем дескриптор сокета
		return;
	else 		//подключились
		{
		    printf("Установлено соединение с %s:%s\n", SERVER_IP, LS_PORT);
		}
}
Переменная socket передаётся в функцию OpenSock() по значению. Это значит, что все изменения, которые производятся с ней внутри функции, теряются при выходе из неё.
Поэтому надо сделать, например так:

Код: Выделить всё

void OpenSock (int *socket, byte nm_socket_msg[] )
{
    *socket = connectsock ( SERVER_IP, LS_PORT, "tcp" );

    if(*socket < 0)	//проверяем дескриптор сокета
		return;
	else 		//подключились
		{
		    printf("Установлено соединение с %s:%s\n", SERVER_IP, LS_PORT);
		}
}
То есть, передаём в функцию указатель на переменную для сокета. Функция теперь кладёт по этому адресу результат подключения.
И далее:

Код: Выделить всё

void main(void)
{
    OpenSock(&net_socket, net_msg);
    if (net_socket>=0)
    {
        Read_Socket(net_socket, net_msg, 16);
        Write_Socket(net_socket, net_msg, 16);
...
Как-то так.
Контактная информация:
Грызет канифоль
Сообщения: 298
Зарегистрирован: Ср дек 30, 2009 09:55:39

Сообщение kolobok0 »

Кислый писал(а):...то все!! крах и тарабах!!! трындец !!! не читаем и не пишем ( о чем сведетельствует переменная n, смотри листинг ниже )

Код: Выделить всё

void Read_Socket (int socket, byte nm_socket_msg[], int len)
{   int n;
    n = recv(socket, nm_socket_msg, len, 0);
    printf("%i\n", n);
    view_pkt(nm_socket_msg, 1);
}
...
....
что конкретнее происходит - опишите.
насколько я понимаю вы иногда получаете n отличное от посылаемой длины? :)

открываем МСДН, внимательно читаем...
TCP - протокол потоковый
если ошибку не видите - повторяете как мантру. потоковый, потоковый, потоковый. пока не снизойдёт озарение!!!
потоковый - это значит что вам никто и не обещал что прийдёт n пример:
послали 10000 (попробуйте кстати - на больших сразу заметно о чём речь.) байт
принимать думаете будете 10000 ? :)
вы можете принять 1000 + 300 + 10 + 8690, а может 3000+5000+1000+500+500 это протоколом НЕ! гарантируется.

надеюсь суть поняли
(круглый)
ЗЫ
Это типичная ошибка с сокетами. Увы такого кода не рабочего в инете пруд пруди. Ударная нагрузка сразу выявит эти траблы.
Реклама
Эиком - электронные компоненты и радиодетали
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2095
Зарегистрирован: Чт апр 08, 2010 18:50:01
Откуда: Краснодар

Сообщение Кислый »

нет. если n -1 - то трындец. а прием или передача - максимум по 256 байт
RETI ;рети-рети интеррапт, через шины данных тракт, через память, через порт, возвращайся в главный код
@hobbyelectronics
Контактная информация:
Реклама
Грызет канифоль
Сообщения: 298
Зарегистрирован: Ср дек 30, 2009 09:55:39

Сообщение kolobok0 »

Кислый писал(а):нет. если n -1 - то трындец. а прием или передача - максимум по 256 байт

256 - это пока в тепличных условиях работать будет. чуть что посерьёзнее - будет задница.
вам выше правильно сказали - вы передаёте в опен переменныу сокет типа инт. с чего вы взяли что она вернёт вам значение из функции? эта переменная на стэке. стэк при выходе из функции разрушится. вам необходимо передать ссылку(референц) на сокет типа инт, либо указатель на сокет типа инт. и вот тогда работать будет.

но повторюсь - функция приёма у вас левая. постить МСДН сюда не буду - гляньте там. Хоть он и содержит ошибки, но в данном разделе стоит к нему прислушаться. Там рабочий код приведён.

удачи вам
(круглый)
Реклама
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2095
Зарегистрирован: Чт апр 08, 2010 18:50:01
Откуда: Краснодар

Сообщение Кислый »

угу. давайте бить из пушки по комарам :)
RETI ;рети-рети интеррапт, через шины данных тракт, через память, через порт, возвращайся в главный код
@hobbyelectronics
Контактная информация:
Грызет канифоль
Сообщения: 298
Зарегистрирован: Ср дек 30, 2009 09:55:39

Сообщение kolobok0 »

Кислый писал(а):угу. давайте бить из пушки по комарам :)
в образовательных целях:
на сегоднешний момент времени, есть драйвера (под форточки) которые могут сидеть в сетевой цепочки и отдавать (при необходимости) по байтно.

ваше право делать софт который будет глючить в данных условиях, потому как не правильно используете протокол TCP.

удачи вам
она вам пригодится
(круглый)
Ответить

Вернуться в «Интеграция с ПК»