Сетевое программирование, сокеты (help!)

Модератор: Модераторы разделов

Аватара пользователя
rza
Сообщения: 105
ОС: Linux Mint 11 Katya

Re: Сетевое программирование, сокеты

Сообщение rza »

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

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>

char message[30];
char buf[sizeof(message)];

int sock;


void  * f_zap()
{
  for (;;)
   {
     scanf("%s",message);
     send(sock, message, sizeof(message), 0);
   }
}
void * f_rec()
{
  for(;;)
   {
     printf("%s",">>");
     recv(sock, buf, sizeof(message), 0);
     printf(buf);
    }
}

int main()
{
    int id1, id2, result;
    pthread_t thread1, thread2;

    struct sockaddr_in addr;

    sock = socket(AF_INET, SOCK_STREAM, 0);
    if(sock < 0)
    {
        perror("socket");
        exit(1);
    }

    addr.sin_family = AF_INET;
    addr.sin_port = htons(3425); // или любой другой порт...
    addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
    if(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
    {
        perror("connect");
        exit(2);
    }
    id1 = 1;
    result = pthread_create(&thread1, NULL, f_zap, &id1);
    id2 = 2;
    result = pthread_create(&thread2, NULL, f_rec, &id2);
    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);
    close(sock);

    return 0;
}

исправил немного. такая проблема - отправляю сообщение - а пока enter не нажму его не выводит на экран. сервер - эхо. ?
Спасибо сказали:
Аватара пользователя
AestheteAnimus
Сообщения: 135
ОС: FreeBSD 8.0-RELEASE amd64

Re: Сетевое программирование, сокеты

Сообщение AestheteAnimus »

rza писал(а):
18.12.2008 20:04
исправил немного. такая проблема - отправляю сообщение - а пока enter не нажму его не выводит на экран. сервер - эхо. ?

Так и должно быть. Пока не нажмете энтер, поток блокируется в функции чтения строки из терминала.

Здесь еще такой момент:

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

send(sock, message, sizeof(message), 0);

Зачем слать весь буфер? Строка может быть короче, а за ней скорее всего будет мусор. Да и буфер нужно сделать больше, хотя бы 4К.

Про другие ошибки я уже писал.

P.S. Кстати да, ввел в некоторое заблуждение, в pthread_join нужно передавать естесственно не указатель.
Спасибо сказали:
Аватара пользователя
rza
Сообщения: 105
ОС: Linux Mint 11 Katya

Re: Сетевое программирование, сокеты

Сообщение rza »

>>Так и должно быть. Пока не нажмете энтер, поток блокируется в функции чтения строки из терминала.
а можно ли это както исправить?
Спасибо сказали:
Аватара пользователя
AestheteAnimus
Сообщения: 135
ОС: FreeBSD 8.0-RELEASE amd64

Re: Сетевое программирование, сокеты

Сообщение AestheteAnimus »

rza писал(а):
19.12.2008 10:04
>>Так и должно быть. Пока не нажмете энтер, поток блокируется в функции чтения строки из терминала.
а можно ли это както исправить?

Можно, читайте про неканонический режим терминала
Спасибо сказали:
Аватара пользователя
AestheteAnimus
Сообщения: 135
ОС: FreeBSD 8.0-RELEASE amd64

Re: Сетевое программирование, сокеты

Сообщение AestheteAnimus »

Вообще, это можно сделать так:

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

#include <termios.h>
...
struct termios termopt;

tcgetattr(fileno(stdin), &termopt);
termopt.c_lflag &= ~(ICANON | ECHO);
termopt.c_cc[VTIME] = 0;
termopt.c_cc[VMIN] = 1;
tcsetattr(fileno(stdin), TCSANOW, &termopt);

'VMIN' - минимальноей количество символов, которое может быть прочитано с терминала. 'VTIME' - задержка, перед чтением. Этим параметром можно поиграться для лучше загруженности потока в сторону сервера.

Здесь, стоит отметить, уже нет смысла польоваться функциями stdio, а вместо этого и для чтения/записи с терминала лучше использовать те же системные вызовы recv/send.
Спасибо сказали:
Аватара пользователя
Portnov
Модератор
Сообщения: 1786
Статус: Матёрый линуксоид
ОС: Debian testing/unstable

Re: Сетевое программирование, сокеты

Сообщение Portnov »

Товарищи, всё проще, не надо никаких termios. man 3 setbuf, man 3 setvbuf. Эти функции устанавливают режим буферизации в стандартной библиотеке libc.
Работа: Ubuntu 9.10
Дом: Debian testing/unstable и на всякий случай winxp в virtualbox.
Для разнообразия: моя домашняя страница -http://iportnov.ru
Спасибо сказали:
Аватара пользователя
AestheteAnimus
Сообщения: 135
ОС: FreeBSD 8.0-RELEASE amd64

Re: Сетевое программирование, сокеты

Сообщение AestheteAnimus »

Portnov писал(а):
19.12.2008 19:34
Товарищи, всё проще, не надо никаких termios. man 3 setbuf, man 3 setvbuf. Эти функции устанавливают режим буферизации в стандартной библиотеке libc.

Хм, а как отключить эхо в таком случае?
Спасибо сказали:
Аватара пользователя
Portnov
Модератор
Сообщения: 1786
Статус: Матёрый линуксоид
ОС: Debian testing/unstable

Re: Сетевое программирование, сокеты

Сообщение Portnov »

Ну echo - это уже к termios. Я про буферизацию говорил.
Работа: Ubuntu 9.10
Дом: Debian testing/unstable и на всякий случай winxp в virtualbox.
Для разнообразия: моя домашняя страница -http://iportnov.ru
Спасибо сказали:
Аватара пользователя
rza
Сообщения: 105
ОС: Linux Mint 11 Katya

Re: Сетевое программирование, сокеты

Сообщение rza »

а с termios просто вставить этот кусок исходника и все?
Спасибо сказали:
Аватара пользователя
AestheteAnimus
Сообщения: 135
ОС: FreeBSD 8.0-RELEASE amd64

Re: Сетевое программирование, сокеты

Сообщение AestheteAnimus »

rza писал(а):
21.12.2008 19:21
а с termios просто вставить этот кусок исходника и все?

Вообще лучше, чтоб Вы его осмысли и написали сами.
Спасибо сказали:
Аватара пользователя
rza
Сообщения: 105
ОС: Linux Mint 11 Katya

Re: Сетевое программирование, сокеты

Сообщение rza »

>> Вообще лучше, чтоб Вы его осмысли и написали сами.
ну это конечно. но в моем коде должны появится эти строчки?
Спасибо сказали:
Аватара пользователя
AestheteAnimus
Сообщения: 135
ОС: FreeBSD 8.0-RELEASE amd64

Re: Сетевое программирование, сокеты

Сообщение AestheteAnimus »

rza писал(а):
21.12.2008 20:11
ну это конечно. но в моем коде должны появится эти строчки?

Только при соблюдении лицензионного соглашения. Эти строки - моя интеллектуальная собственность. Ссылка на автора (на меня) и денежные отчисления обязательны. :D

OFF
Админы, хватит чудить с картинками!
Спасибо сказали:
Аватара пользователя
rza
Сообщения: 105
ОС: Linux Mint 11 Katya

Re: Сетевое программирование, сокеты

Сообщение rza »

сейчас очередной раз скомпилил... не вставлял пока Ваш кусок исходника , а сокет не блокировал ничего! не надо было жать энтер! удивился. что это может быть? при использовании gets компилятор выдает
gets - dangerous function should not be used . scanf читает строку до пробела. помогите мне ввести строку пл3.
Спасибо сказали:
Аватара пользователя
AestheteAnimus
Сообщения: 135
ОС: FreeBSD 8.0-RELEASE amd64

Re: Сетевое программирование, сокеты

Сообщение AestheteAnimus »

rza писал(а):
21.12.2008 22:37
сейчас очередной раз скомпилил... не вставлял пока Ваш кусок исходника , а сокет не блокировал ничего! не надо было жать энтер! удивился. что это может быть?

Причем тут сокет? Вводя данные с терминала, пока не нажмете энтер, данные не будут копироваться из системного буфера. Определенно, Вы что-то путаете.

Компилятор ругается на то, что в gets нет никакой возможности защитить от переполнения буфера. Используйте fgets.
Спасибо сказали:
Аватара пользователя
rza
Сообщения: 105
ОС: Linux Mint 11 Katya

Re: Сетевое программирование, сокеты

Сообщение rza »

я спутал.... но все же. почему без дополнения вашего кода в свой данные стали выводиться из буфера без нажатия энтера? ничего не пойму.....
помогите с написанием makefile. никак не разберусь
Спасибо сказали:
Аватара пользователя
AestheteAnimus
Сообщения: 135
ОС: FreeBSD 8.0-RELEASE amd64

Re: Сетевое программирование, сокеты

Сообщение AestheteAnimus »

rza писал(а):
21.12.2008 23:47
почему без дополнения вашего кода в свой данные стали выводиться из буфера без нажатия энтера? ничего не пойму.....

Нет, Вы как раз сейчас путаете. Не должно эхо выводиться до нажатия энтера.

rza писал(а):
21.12.2008 23:47
помогите с написанием makefile. никак не разберусь

Тогда уж давайте исходник, к чему Makifile писать.
Спасибо сказали:
Аватара пользователя
rza
Сообщения: 105
ОС: Linux Mint 11 Katya

Re: Сетевое программирование, сокеты

Сообщение rza »

исходник почти тот же что был выше.
там компилятор вызывался
gcc threads.c -D_REENTERANT -I/usr/include/nptl -L/usr/lib/nptl –lpthread -o threads
Спасибо сказали:
Аватара пользователя
AestheteAnimus
Сообщения: 135
ОС: FreeBSD 8.0-RELEASE amd64

Re: Сетевое программирование, сокеты

Сообщение AestheteAnimus »

Не... так не пойдет. Изучайте:
http://linfoline.homedns.org/gnu-make-ru/gnu-make-ru.html
Спасибо сказали:
Аватара пользователя
rza
Сообщения: 105
ОС: Linux Mint 11 Katya

Re: Сетевое программирование, сокеты

Сообщение rza »

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

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>

char message[30];
char buf[sizeof(message)];

int sock;


void  * f_zap(void)
{
  for (;;)
   {
     fgets(message, sizeof(message), stdin);
     send(sock, message, sizeof(message), 0);
   }
}
void * f_rec(void)
{
  for(;;)
   {
     recv(sock, buf, sizeof(message), 0);
     printf(">>");
     printf(buf);
     printf("\n");
    }
}

int main()
{
    int id1, id2;
    pthread_t thread1, thread2;

    struct sockaddr_in addr;

    sock = socket(AF_INET, SOCK_STREAM, 0);
    if(sock < 0)
    {
        perror("socket");
        exit(1);
    }

    addr.sin_family = AF_INET;
    addr.sin_port = htons(3425); // или любой другой порт...
    addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
    if(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
    {
        perror("connect");
        exit(2);
    }
    printf("running\n");
    id1 = 1;
    pthread_create(&thread1, NULL, f_zap(), &id1);
    id2 = 2;
    pthread_create(&thread2, NULL, f_rec(), &id2);
    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);
    close(sock);

    return 0;
}
вот он исходник. сам я не разрулю мэйк это точно...
Спасибо сказали:
Аватара пользователя
rza
Сообщения: 105
ОС: Linux Mint 11 Katya

Re: Сетевое программирование, сокеты

Сообщение rza »

вот в моей проге в бесконечном цикле вувод и вывод. программа некорректно завершается. до pthread_join(thread1, NULL); pthread_join(thread2, NULL); дело не доходит. как сделать выход корректным? чтоб закрыть и сервер и клиент? помогите пожалуйста.
Спасибо сказали:
Аватара пользователя
rza
Сообщения: 105
ОС: Linux Mint 11 Katya

Re: Сетевое программирование, сокеты

Сообщение rza »

подключил сеть к компу. прописал ай пи днс ерверы и тд. и прога перестала работать.... как это исправить?
Спасибо сказали:
Аватара пользователя
AestheteAnimus
Сообщения: 135
ОС: FreeBSD 8.0-RELEASE amd64

Re: Сетевое программирование, сокеты

Сообщение AestheteAnimus »

Так... наконец-то добрался и до этого поста...

rza писал(а):
24.12.2008 22:31
вот он исходник. сам я не разрулю мэйк это точно...

Этот код работать не будет в принципе. Подсказываю, вот в этих строчках:

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

pthread_create(&thread1, NULL, f_zap(), &id1);
...
pthread_create(&thread2, NULL, f_rec(), &id2);


Что касается make-а, то скажите, для чего он Вам нужен? Если для сопровождения программы и ее кросскомпиляции, то лучше почитать документацию на autoconf. Если он нужен для собственного удобства, то лучше его сделать предельно простым, например так:

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

PROGNAME = sockcli

# Настройка утилит и флагов
CC      =   gcc
OBJDUMP =   objdump
CFLAGS  =   -Wall -pedantic -O3 -std=gnu99
LFLAGS  =   -Wl,-Map,$(PROGNAME).map


# Подключаемые библиотеки
LIBS = -lpthread
# Дополнительные дефайны
CDEFS = -D_REENTERANT

# Перечисляем через пробел все исходники
# (в данном примере, только C-исходники)
CSRC = main.c other.c

# Копируем список, заменяя расширения на .o
OBJ = $(CSRC:.c=.o)

build:      elf lss
rebuild:    clean build

# Цель для получения объектных файлов
# (Я не использую GNU make поэтому здесь правило в суффиксной форме)
# Для GNU make можно написать так:
#%.o: %.c
#    $(CC) $(CFLAGS) $(CDEFS) -c $<
#
.c.o:
    $(CC) $(CFLAGS) $(CDEFS) -c $<

# Линковка
elf: $(OBJ)
    $(CC) $(LFLAGS) $(LIBS) -o $(PROGNAME) $(OBJ)

# Генерация асмового листинга (бывает полезен)
lss: elf
    $(OBJDUMP) -h -S $(PROGNAME) > $(PROGNAME).lss

clean:
    rm -rf *.o *.lss *.map $(PROGNAME)


rza писал(а):
25.12.2008 17:06
вот в моей проге в бесконечном цикле вувод и вывод. программа некорректно завершается. до pthread_join(thread1, NULL); pthread_join(thread2, NULL); дело не доходит. как сделать выход корректным? чтоб закрыть и сервер и клиент? помогите пожалуйста.

При выходе (даже некорректном) все дескрипторы закрываются, в том числе и дескрипторы сокетов. Соответстенно, обмен пакетами FIN будет сделан в любом случае.

rza писал(а):
25.12.2008 21:08
подключил сеть к компу. прописал ай пи днс ерверы и тд. и прога перестала работать.... как это исправить?

Когда подправите ту ошибку в запуске потоков (а заодно и все остальные), скорее всего и эта проблема исчезнет. А вообще подобного рода проблемы обычно отлаживаются netstat-ом - проверкой какие сокеты прослушиваются, покаким идет обмен etc.
Спасибо сказали:
Аватара пользователя
rza
Сообщения: 105
ОС: Linux Mint 11 Katya

Re: Сетевое программирование, сокеты

Сообщение rza »

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

#include <sys/types.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <pthread.h>

#include <stdlib.h>

#include <stdio.h>

#include <errno.h>

char ext[]="exit";

char message[30];

char buf[sizeof(message)];



int sock;


void  * f_zap()
{
  for (;;)
   {
     fgets(message, sizeof(message), stdin);
     if(strstr(message,ext))
     {
      send(sock, ext, sizeof(ext), 0);
      return;
     }
     send(sock, message, sizeof(message), 0);
   }
}
void * f_rec()
{
  for(;;)
   {
     recv(sock, buf, sizeof(message), 0);
     if (strstr(buf,ext))
     {
      printf("interlocutor is gone.\n");
      return;
     }
     printf(">>");
     printf(buf);
     printf("\n");
    }
}



int main()

{

    int id1, id2, result;

    pthread_t thread1, thread2;



    struct sockaddr_in addr;



    sock = socket(AF_INET, SOCK_STREAM, 0);

    if(sock < 0)

    {

        perror("socket");

        exit(1);

    }



    addr.sin_family = AF_INET;

    addr.sin_port = htons(3425);

    addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);

    if(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)

    {

        perror("connect");

        exit(2);

    }
    printf("running\n");
    printf("if you want to exit program - enter exit\n");
    printf("if your interlocutor is gone - enter exit\n");

    id1 = 1;

    result = pthread_create(&thread1, NULL, f_zap, &id1);

    id2 = 2;

    result = pthread_create(&thread2, NULL, f_rec, &id2);

    pthread_join(thread1, NULL);
    printf("1 - closed\n");

    pthread_join(thread2, NULL);
    printf("2-closed\n");

    close(sock);

    printf("socket closed\n");
    scanf("%s",ext);

    return 0;

}

вот последняя версия. баги в студию!
Спасибо сказали:
Аватара пользователя
AestheteAnimus
Сообщения: 135
ОС: FreeBSD 8.0-RELEASE amd64

Re: Сетевое программирование, сокеты

Сообщение AestheteAnimus »

rza писал(а):
28.12.2008 21:43
вот последняя версия

Охохох...

1.

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

char message[30];

Если обмен происходит строками, то такой буфер смехотворно мал.

2.

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

void  * f_zap()
void * f_rec()


Для потока нужна функция вида:

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

void* func(void* arg)

Но не

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

void* func(void)
и точно не

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

void* func()


3.

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

send(sock, message, sizeof(message), 0);

Чуть выше Вы gets-ом читаете строку. Но вот этой строчко Вы пошлете буфер циликом, а не строку. В результате в эхе будет случайный мусор.

4.

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

recv(sock, buf, sizeof(message), 0);

А откуда такая увереность, что recv возратит именно строку (тоесть последовательность байтов, завершунных нулем)? recv возращает все имеющиеся в системном буфере данные, но не более, чем размер приемного буфера, ни о каких строках recv знать не знает. Так что и здесь можно ожидать отображения в консоли всякого мусора.

5.

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

printf(buf);

Ну нельзя так делать! :angry:

6.

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

addr.sin_family = AF_INET;
...

Переменная addr выделяется на стеке, а значит компилятора не обязан ее обнулять. Так что перед ее использованием нужно сделать например так:

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

memset(&addr, 0, sizeof(addr));


Вроде пока все...

В принципе, я бы сделал это примерно так:
Сервер:

Клиент:

wraps.c:

wraps.h:
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Спасибо сказали:
Аватара пользователя
rza
Сообщения: 105
ОС: Linux Mint 11 Katya

Re: Сетевое программирование, сокеты

Сообщение rza »

предупреждение: incompatible implicit declaration of built-in function ‘memset’ ???
проблем с мусором нет. это программа студента 2 курса! не забывайте. и Ваш пример для меня очень сложен.
подправил функции потока и добавил мемсет.
кстати такое предупреждение и из за strstr. что это?
Спасибо сказали:
Аватара пользователя
AestheteAnimus
Сообщения: 135
ОС: FreeBSD 8.0-RELEASE amd64

Re: Сетевое программирование, сокеты

Сообщение AestheteAnimus »

rza писал(а):
29.12.2008 09:25
предупреждение: incompatible implicit declaration of built-in function ‘memset’ ???

Бред какой-то... memset - стандартная функция libc, находится в <string.h> который инклудится в "wraps.h". Вы же годались, что wraps.c/wraps.h общие и их надо скопировать и к исходникам клиента и к исходникам сервера.

rza писал(а):
29.12.2008 09:25
и Ваш пример для меня очень сложен.
подправил функции потока и добавил мемсет.

Которая часть его сложна? Соответственно, если есть вопросы - могу ответить.
Спасибо сказали:
Аватара пользователя
rza
Сообщения: 105
ОС: Linux Mint 11 Katya

Re: Сетевое программирование, сокеты

Сообщение rza »

бред не бред а предупреждение. такое же предупреждение про strstr. тот же стринг аш
Спасибо сказали:
Аватара пользователя
AestheteAnimus
Сообщения: 135
ОС: FreeBSD 8.0-RELEASE amd64

Re: Сетевое программирование, сокеты

Сообщение AestheteAnimus »

rza писал(а):
29.12.2008 16:55
бред не бред а предупреждение. такое же предупреждение про strstr. тот же стринг аш

Такое сообщение?

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

main.c: In function 'main':
main.c:51: warning: implicit declaration of function 'memset'
main.c:51: warning: incompatible implicit declaration of built-in function 'memset'

Значит не приинклуден <string.h>
Спасибо сказали:
Аватара пользователя
rza
Сообщения: 105
ОС: Linux Mint 11 Katya

Re: Сетевое программирование, сокеты

Сообщение rza »

дело в том что он приинклуден
Спасибо сказали:
Аватара пользователя
AestheteAnimus
Сообщения: 135
ОС: FreeBSD 8.0-RELEASE amd64

Re: Сетевое программирование, сокеты

Сообщение AestheteAnimus »

rza писал(а):
29.12.2008 18:02
дело в том что он приинклуден

Не компилится мой исходник? Не может быть - у меня компилится. Если Ваш, то проверяйте, значит string.h не приинклуден.

rza писал(а):
28.12.2008 21:43

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

#include <sys/types.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <pthread.h>

#include <stdlib.h>

#include <stdio.h>

#include <errno.h>

...


Я здесь не вижу string.h
Спасибо сказали: