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

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

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

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

Сообщение rza »

получилась такая концепция: сервер работает постоянно(эхо-сервер). клиент запускается, отправляет сообщение, принимает с сервера, выводит на экран и заканчивает работу. нужно сделать так чтоб можно было отправлять сообщения и принимать их как на сервере, так и на клиенте. и чтоб клиент сам не завершал работу. не могу додуматься как это сделать. Подскажите пожалуйста как это можно сделать.
Спасибо сказали:
MiK13
Сообщения: 1263
ОС: Linux Debian

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

Сообщение MiK13 »

rza писал(а):
09.12.2008 16:59
получилась такая концепция: сервер работает постоянно(эхо-сервер). клиент запускается, отправляет сообщение, принимает с сервера, выводит на экран и заканчивает работу. нужно сделать так чтоб можно было отправлять сообщения и принимать их как на сервере, так и на клиенте. и чтоб клиент сам не завершал работу. не могу додуматься как это сделать. Подскажите пожалуйста как это можно сделать.

Не поняно, что именно надо. Какие сообщения, кто и от кого должен принимать? Что имеется ввиду под сервером и клиентом?
Что значит "чтоб клиент сам не завершал работу"? А что он должен делать?
skillergti писал(а):
05.12.2008 01:21
Очевидно, Брюс Моли "Unix/Linux теория и практика программирования".

Нет, Кейт Хэвиленд, Дайна Грэй, Бен Салама. "Системное программирование в UNIX" Руководство программиста по разработке ПО
Есть на обложке ещё более мелкая заись "Универсальная среда программирования"
Спасибо сказали:
Аватара пользователя
rza
Сообщения: 105
ОС: Linux Mint 11 Katya

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

Сообщение rza »

клиент отправляет сообщение - эхо-сервер его возвращает - клиент закрывается. а на да чтоб
запустить клиент и сервер - передавать сообщения и выводить их и там и там.
сервер - программа которая создаёт сокет.
клиент - программа которая соединяется с этим сокетом.
надо сделать так чтоб когда была включена программа мне выводились бы все присланные сообщения и я бы мог в любой момент отправить свое.
Спасибо сказали:
Grom
Сообщения: 260
ОС: Debian Etch, RHEL-5.4

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

Сообщение Grom »

Посмотри в направлении функции select()
Послужной список: Slackware-3.x, RedHat-4.x,5.x,6.x,7.x, FedoraCore-3, Debian Etch/Lenny
Осваиваю: RHEL-5.4
Спасибо сказали:
Аватара пользователя
rza
Сообщения: 105
ОС: Linux Mint 11 Katya

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

Сообщение rza »

посмотрел с select()
сложновато. ничего не понял. а что если запустить 2 функции в 2 потоках? сложно это реализовать? чтоб 1ф-ция выводила а 2 вводила в сокает. ????
Спасибо сказали:
MiK13
Сообщения: 1263
ОС: Linux Debian

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

Сообщение MiK13 »

rza писал(а):
09.12.2008 19:03
клиент отправляет сообщение - эхо-сервер его возвращает - клиент закрывается.

Клиент закрывается, когда в нём выполняется exit или return или просто достигается конец функции.
rza писал(а):
09.12.2008 19:03
надо сделать так чтоб когда была включена программа мне выводились бы все присланные сообщения и я бы мог в любой момент отправить свое.

Т.е. надо сделать что-то вроде IRC-сервера? Т.е. клиент тоже должен быть сервером, чтобы принимать сообзения от основного сервера?
Но тогда и на сервере надо вести список всех подключённых к нему клиентов и при получении сообщения от любого посылать это сообщение всем остальным.

Что касается функции select()... я ей пока ещё ни разу не пользовался. Как я понимаю, она позволяет в одном потоке выполнять чтение из нескольких "каналов" (файлов) -- в зависимости от того, где раньше появится информация.
В данном варианте, думаю, надо организовывать чтение как из сокета, который связан с сервером, так и из файла клавиатурного ввода. При появлении данных с клавиатуры -- введённую строку передавать на сервер, а при появлении данных от севера -- полученную информацию выводить на терминал.
Спасибо сказали:
Аватара пользователя
rza
Сообщения: 105
ОС: Linux Mint 11 Katya

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

Сообщение rza »

а как проверять появление данных с клавиатуры? и как проверять появления данных с сервера?
>>>>
Т.е. надо сделать что-то вроде IRC-сервера? Т.е. клиент тоже должен быть сервером, чтобы принимать сообзения от основного сервера?
>>>>
да! если можете напишите функции которіе применять или маленький кусочек исходника (фрагмент).
Спасибо сказали:
MiK13
Сообщения: 1263
ОС: Linux Debian

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

Сообщение MiK13 »

rza писал(а):
11.12.2008 19:52
если можете напишите функции которіе применять или маленький кусочек исходника (фрагмент).

К сожалению пока этого сделать не могу. Просто потому, что такую задачу решать ещё не приходилось.
Но могу предложить почитать фрагмент из упомянутой мной книги про функцию select
Там есть пример программы, правда, я её не проверял и поэтому в ней возможны ошибки (я делал страницы с помощью ФайнРидера, а он может понимать текст не так, как человек)
Что касается чтение данных с клавиатуры, то его можно выполнять по read(0,... . Т.к. дексриптор 0 связан с stdin (1 -- c stdout и 2 -- c stderr).
Ну а дальше остаётся только разобраться как работает та программа
Спасибо сказали:
Grom
Сообщения: 260
ОС: Debian Etch, RHEL-5.4

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

Сообщение Grom »

rza писал(а):
10.12.2008 08:31
посмотрел с select()
сложновато. ничего не понял. а что если запустить 2 функции в 2 потоках? сложно это реализовать? чтоб 1ф-ция выводила а 2 вводила в сокает. ????


Приношу свои извинения, не посмотрел внимательно куда ссылка идёт. В качестве реабилитации привожу кусок своего древнего кода где использовалась функция select():

Код:

int main(void) { int i, len, strob; int SelectResult; fd_set fdset, fdred; for(i=0;i<MAX_USER;i++) { ChannelCount[i] = 0; csock[i] = 0; } get_socket(); for(;; ) { FD_ZERO(&fdset); FD_SET(sock, &fdset); FD_SET(ssock,&fdset); FD_ZERO(&fdred); #ifdef NO_INMOS FD_SET(tsock,&fdset); strob = tsock; #else strob = ssock; #endif for( i=0; i<MAX_USER; i++ ) if( csock[i] ) { FD_SET(csock[i], &fdset); if( strob < csock[i] ) { strob = csock[i]; } } SelectResult = select(strob+1, &fdset, NULL, NULL, NULL); if( SelectResult >0 ) { /* Ask from new Client for connection */ if( FD_ISSET(sock, &fdset) || FD_ISSET(ssock,&fdset) ) { if( FD_ISSET(sock, &fdset) ) bsock = sock; else bsock = ssock; nsock = accept(bsock, (struct sockaddr *)0, (int *)0); if (nsock == -1) { #ifdef BSD if( errno == EINTR ) { signal(SIGCHLD, sigchld); continue; } #endif ; } else { len = read_s(nsock, sv.string, sizeof(sv.string)); if( len > 0 ) { client_registration(nsock, sv.string); } if(nsock) nsock = 0; } } /* if */ else { for( i=0; i<MAX_USER; i++ ) if(csock[i]) if( FD_ISSET(csock[i], &fdset) ) /* || FD_ISSET(csock[i], &fdred) ) */ { s_client_event(i); } } /* else */ } /* if( select() ) */ } /* for(;; ) */ } /* main() */

Сперва создается список сокетов функциями FD_ZERO(), FD_SET(), FD_ISSET(), а потом select() проверяет, пришло ли что-нибудь по ним. Запросы обрабатывает в порядке поступления. Подробности смотри в описаниях функций.
Послужной список: Slackware-3.x, RedHat-4.x,5.x,6.x,7.x, FedoraCore-3, Debian Etch/Lenny
Осваиваю: RHEL-5.4
Спасибо сказали:
Аватара пользователя
rza
Сообщения: 105
ОС: Linux Mint 11 Katya

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

Сообщение rza »

объясните как правильно работать с потоками? какие особенности? какие функции применять? если может кто то с этим сталкивался может что подскажет. опять же может кусочек исходника.
Спасибо сказали:
Аватара пользователя
rza
Сообщения: 105
ОС: Linux Mint 11 Katya

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

Сообщение rza »

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

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

Сообщение AestheteAnimus »

rza писал(а):
09.12.2008 16:59
получилась такая концепция: сервер работает постоянно(эхо-сервер). клиент запускается, отправляет сообщение, принимает с сервера, выводит на экран и заканчивает работу. нужно сделать так чтоб можно было отправлять сообщения и принимать их как на сервере, так и на клиенте. и чтоб клиент сам не завершал работу. не могу додуматься как это сделать. Подскажите пожалуйста как это можно сделать.

Читать Стивенса! У него эта задача во все щели насилуется, вернее, на ее примере показываются различные подходы.

rza писал(а):
09.12.2008 19:03
сервер - программа которая создаёт сокет.
клиент - программа которая соединяется с этим сокетом.

Ничего не путаете? На сервере создается прослушиваемый сокет, на стороне клиента - присоединенный.

rza писал(а):
12.12.2008 23:14
объясните как правильно работать с потоками? какие особенности? какие функции применять? если может кто то с этим сталкивался может что подскажет. опять же может кусочек исходника.

Насчет посикс-потоков можно начать вот с этого: https://computing.llnl.gov/tutorials/pthreads/

rza писал(а):
12.12.2008 23:48
и ещё . сокет создается в main(). как сделать чтоб его можна было использовать в других функциях тоесть сделать как бы глобальной переменной?? какого она типа - переменная имя сокета??

Дескриптор сокета - это просто целое число, притом, int. Таким образом, достаточно просто передать его по значению в нужную Вам функцию.
Спасибо сказали:
Аватара пользователя
rza
Сообщения: 105
ОС: Linux Mint 11 Katya

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

Сообщение rza »

а вот ещё вопрос. операторы перегружены << >>. но я могу их использовать только в main() для других функций которые я создал он не перегружен. в чем дело? помогите. кстати не найду ссылку на скачку Стивенса. или только покупать? а покупать дороговато.
Спасибо сказали:
Аватара пользователя
AestheteAnimus
Сообщения: 135
ОС: FreeBSD 8.0-RELEASE amd64

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

Сообщение AestheteAnimus »

rza писал(а):
13.12.2008 12:01
помогите. кстати не найду ссылку на скачку Стивенса. или только покупать?

Лучше конечно купить, ибо бумага, ИМХО, удобнее. Но если нет, то вроде гуглится нормально ;)
http://www.google.com/search?hl=en&cli...amp;btnG=Search

rza писал(а):
13.12.2008 12:01
а вот ещё вопрос. операторы перегружены << >>. но я могу их использовать только в main() для других функций которые я создал он не перегружен. в чем дело?

Во первых, для чего Вы используете <<, >>? Во вторых, не надо их использовать, дабы не иметь проблем с буферизацией stdstream.
Спасибо сказали:
Аватара пользователя
rza
Сообщения: 105
ОС: Linux Mint 11 Katya

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

Сообщение rza »

для простоты работы с скетами было сделано вот что. перегрузка << >>. string>>socket в строковую переменную запись. вот так. или не стоит єтого делать?
спасибо большое за Стивенса! книга очень хорошая.
Спасибо сказали:
Аватара пользователя
AestheteAnimus
Сообщения: 135
ОС: FreeBSD 8.0-RELEASE amd64

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

Сообщение AestheteAnimus »

rza писал(а):
13.12.2008 13:27
для простоты работы с скетами было сделано вот что. перегрузка << >>. string>>socket в строковую переменную запись. вот так. или не стоит єтого делать?

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

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

Сообщение rza »

подскажите как сделать так чтоб перегрузка работала во всех функциях, а не только в main()
Спасибо сказали:
Аватара пользователя
rza
Сообщения: 105
ОС: Linux Mint 11 Katya

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

Сообщение rza »

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

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

Сообщение AestheteAnimus »

rza писал(а):
15.12.2008 17:03
–lpthread не подключается в параметрах компилера. что это может быть?

Как подключаете? (Дайте кусочек make-a, чтоли...)
Спасибо сказали:
MiK13
Сообщения: 1263
ОС: Linux Debian

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

Сообщение MiK13 »

rza писал(а):
15.12.2008 17:03
–lpthread не подключается в параметрах компилера. что это может быть?

А что именно не подключается? –lpthread или -lpthread ?

Сейчас вспоминаю, что у меня как-то была именно эта проблема -- брал код из html текста, а там вместо знака "HYPHEN-MINUS" ('-') оказался знак "EN DASH" ('–')
Причину искал довольно долго.
Спасибо сказали:
Аватара пользователя
rza
Сообщения: 105
ОС: Linux Mint 11 Katya

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

Сообщение rza »

http://citforum.ru/programming/unix/threads/ вот ссылка . копировал прямо со странички. может и вправду
<<вместо знака "HYPHEN-MINUS" ('-') оказался знак "EN DASH" ('–')<< . может кто то попробует скомпилить эту прогу?? всем спасибо.
Спасибо сказали:
MiK13
Сообщения: 1263
ОС: Linux Debian

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

Сообщение MiK13 »

rza писал(а):
16.12.2008 17:20
http://citforum.ru/programming/unix/threads/ вот ссылка . копировал прямо со странички. может и вправду
<<вместо знака "HYPHEN-MINUS" ('-') оказался знак "EN DASH" ('–')<< . может кто то попробует скомпилить эту прогу?? всем спасибо.

Похоже, это именно тот самый пример, на который я не так давно наталкивался
Вот изображение строки, вставленной в geany:

Как видно, чёрточка перед словом lpthread длинее, чем аналогичная перед другими словами. А значит там стоит не обычный знак '-', а другой.
Соответственно, компилятор пытается интерпретировать всё слово "–lpthread" и не понимает его
Замените его на обычный минус и всё должно пройти.
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Спасибо сказали:
Аватара пользователя
rza
Сообщения: 105
ОС: Linux Mint 11 Katya

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

Сообщение rza »

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

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

Сообщение rza »

вот мне нужно сделать клиент который параллельно принимает и отправляет сообщения. я запустил две функции в 2 потоках. функция ввода - запрос ввода строки а потом send(),в бесконечном цикле; функция вывода recv() и тоже в бесконечном цикле. но программа не запускается. компилируется но не запускается. скорее я не правильно что то додумал. помогите пожалуйста.
Спасибо сказали:
Аватара пользователя
AestheteAnimus
Сообщения: 135
ОС: FreeBSD 8.0-RELEASE amd64

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

Сообщение AestheteAnimus »

rza писал(а):
17.12.2008 22:13
вот мне нужно сделать клиент который параллельно принимает и отправляет сообщения.

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

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

Сообщение AestheteAnimus »

rza писал(а):
17.12.2008 22:13
но программа не запускается.

Как это проявляется? Права на выполнение установлены?
Спасибо сказали:
Аватара пользователя
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 (;;) { printf("%s","vvod","/n"); 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); close(sock); return 0; }


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

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

Сообщение AestheteAnimus »

rza писал(а):
18.12.2008 00:05
вот это клиент. а сервер работает как эхо с ним проблем пока нет.

Все не так. См. Стивенс "26.3 Использование потоков в функции str_cli".

Вообще, в глаза бросается следующее:

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

printf("%s","vvod","/n");
Ооочень странный порядок аргументов и их написание

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

scanf("%s",message);
Вы наверное имели ввиду

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

gets(message, sizeof(message), stdin)
?

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

printf(buf);
Нельзя в строку форматирования всталять непроверенные данные. Читайте про уязвимость printf. Опять-таки, наверное Вы имели ввиду:

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

puts(buf);


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

void  * f_zap()
void * f_rec()
Входной параметр для потоков - это void*, но никак не пустой список. Вообще, забудьте в Си писать функции с пустым списком - здесь подобное не то же самое, что в С++.

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

id1 = 1;
id2 = 2;
Зачем? Если поток не принимает никаких данных, то и передайте ему NULL.

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

close(sock);
Как интересно... А с каким же дескриптором у нас будут работать потоки?

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

return 0;
Если мы так сразу выйдем, то заодно прибьем запущенные потоки, в которых выполняется полезная работа. Не правда ли, странно?

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

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

Сообщение rza »

>>Если мы так сразу выйдем, то заодно прибьем запущенные потоки, в которых выполняется полезная работа. Не правда ли, странно?
потоки убиваются. так а как это исправить?

>>close(sock);
а где это писать?

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

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

Сообщение AestheteAnimus »

rza писал(а):
18.12.2008 17:57
>>Если мы так сразу выйдем, то заодно прибьем запущенные потоки, в которых выполняется полезная работа. Не правда ли, странно?
потоки убиваются. так а как это исправить?


После запуска потоков нужно дождаться их завершения:

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

pthread_join(&thread1, NULL);
pthread_join(&thread2, NULL)


rza писал(а):
18.12.2008 17:57
>>close(sock);
а где это писать?

А вот когда потоки завершены можно и закрыть сокет, хотя, при выходе все дескрипторы закрываются автоматически.

rza писал(а):
18.12.2008 17:57
а правильно ли в бесконечном цикле запрашивать ввод??

Это как раз совершенно нормально. Правда, Вам, как я понял, нужно читать строку, а не произвольные данные, поэтому recv здесь так влоб применять нельзя. Ну подумайте, Вы этой функцией читаете какие-то данные, количество которых не превышает заданную длину. Но это не дает никакой гарантии, что в этот буфер будет прочитана строка - в результате Вы почти наверняка выведите мусор, который находится за принимаемым буфером. В общем, посмотрите функцию readline у Стивенса
Спасибо сказали: