Сокеты (клиент-сервер)

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

Аватара пользователя
MUTOgen
Сообщения: 343
Статус: i like the way you move
ОС: OpenSuse 11.1

Сокеты

Сообщение MUTOgen »

Решил реализовать такую модель: есть сервер, есть клиент. Между ними связь такая, что каждая сторона может принимать текстовые сообщения и отправлять. Я решил сделать так: из основного файла server.cpp вызывать новый процесс и грузить в него код server_in.cpp (таким образом в файле server.cpp осуществляется только отправка сообщений, а в server_in.cpp только чтение полученых сообщений), аналгично client.cpp вызывает новый процесс и загружает код cleint_in.cpp (т.е. client.cpp отправляет, а client_in.cpp только читает).

Связь между отправляющим client.cpp и читающим server_in.cpp я поставил например на 3000-ый порт, а связь server.cpp - client_in.cpp на 2000-ый...
Вот тексты программ без include:
server.cpp

Код:

int main(){ struct sockaddr_in local; char buf1[50]; int fd=fork(); if(fd==0){ execlp("/home/download/sockets/server_in","/home/download/sockets/server_in",NULL); std::cerr << "Exec_Err\n"; } local.sin_family=AF_INET; local.sin_port=htons(2000); local.sin_addr.s_addr=htonl(INADDR_ANY); int s=socket(AF_INET, SOCK_STREAM,0); if(s==-1) {std::cerr << "socket\n"; return 1;} int b=bind(s,(struct sockaddr*)&local, sizeof(local)); if(b==-1) {std::cerr << "bind_send\n";return 1;} int l=listen(s,5); while(1){ int a=accept(s,NULL,NULL); std::cout << "Your message: "; std::cin >> buf1; l=send(a,buf1,sizeof(buf1),0); std::cout << buf1 << std::endl; } return 0; }


server_in.cpp

Код:

int main(){ struct sockaddr_in local; char buf1[50]; local.sin_family=AF_INET; local.sin_port=htons(3000); local.sin_addr.s_addr=htonl(INADDR_ANY); int s=socket(AF_INET, SOCK_STREAM,0); if(s==-1) {std::cerr << "socket\n"; return 1;} int b=bind(s,(struct sockaddr*)&local, sizeof(local)); if(b==-1) {std::cerr << "bind_read\n";return 1;} int l=listen(s,5); while(1){ int a=accept(s,NULL,NULL); l=recv(a,buf1,sizeof(buf1),0); std::cout << buf1 << std::endl; } return 0; }


client.cpp

Код:

int main(int argc,char *argv[]){ char buf1[50],buf2[50]; struct sockaddr_in tohost; struct hostent *host; int fd=fork(); if(fd==0){ execlp("/home/download/sockets/client_in","/home/download/sockets/client_in",argv[1],NULL); cerr << "Exec_Err\n"; } if((host=gethostbyname(argv[1])) == NULL) {cerr << "bad_gethost" << endl; return 1;} tohost.sin_family=AF_INET; tohost.sin_port=htons(3000); bcopy(host->h_addr, (struct sockaddr*)&tohost.sin_addr, host->h_length); int s=socket(AF_INET, SOCK_STREAM, 0); if(s==-1) {cerr << "bad_socket" << endl; return 1;} while(1){ int c=connect(s, (struct sockaddr*)&tohost, sizeof(tohost)); if(c!=0) {cerr << "bad_connect_write" << endl;return 1;} cout << "Your message: "; cin >> buf2; c=send(s,buf2,sizeof(buf2),0); cout << buf2 << endl; } return 0; }


client_in.cpp

Код:

int main(int argc,char *argv[]){ struct sockaddr_in local; char buf1[50]; struct hostent *host; if((host=gethostbyname(argv[1])) == NULL) {std::cerr << "bad_gethost" << std::endl; return 1;} local.sin_family=AF_INET; local.sin_port=htons(2000); bcopy(host->h_addr, (struct sockaddr*)&local.sin_addr, host->h_length); int s=socket(AF_INET, SOCK_STREAM,0); if(s==-1) {std::cerr << "socket\n"; return 1;} while(1){ int c=connect(s, (struct sockaddr*)&local, sizeof(local)); if(c!=0) {std::cerr << "bad_connect_read" << std::endl;return 1;} c=recv(s,buf1,sizeof(buf1),0); std::cout << buf1 << std::endl; } return 0; }


Так вот... В результате получаю ошибки у сервера bind_read. Ну и соответственно все мои отправки с клиента бессмысленны....
Может ли вообще работать такая схема? Если да, то где промах? Какие еще схемы такой связи можно организовать (более выгодно)?

P.S. если кто не понял я хотел наладить что-то вроде чата...
Спасибо сказали:
Аватара пользователя
RasenHerz
Сообщения: 1341
ОС: Arch Linux amd64

Re: Сокеты

Сообщение RasenHerz »

почему именно такая сложная и неказистая схема? не проще ли воспользоваться стандартной схемой клиент <-> сервер?
не проще ли воспользоваться, во-первых, одним портом, во-вторых, сделать сервер одновременно и пишущим и читающим (ИМХО это намного легче, чем то что вы придумали=) )
Спасибо сказали:
Аватара пользователя
Rootlexx
Бывший модератор
Сообщения: 4471
Статус: GNU generation
ОС: Debian GNU/Linux

Re: Сокеты

Сообщение Rootlexx »

MUTOgen писал(а):
19.08.2008 14:34
В результате получаю ошибки у сервера bind_read.

Добавьте в обработку ошибок для bind:

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

fprintf (stderr, "bind_read error: %s\n", strerror (errno));

Не забудьте включить файл errno.h и string.h.
Спасибо сказали:
Аватара пользователя
MUTOgen
Сообщения: 343
Статус: i like the way you move
ОС: OpenSuse 11.1

Re: Сокеты

Сообщение MUTOgen »

RasenHerz писал(а):
19.08.2008 15:45
почему именно такая сложная и неказистая схема? не проще ли воспользоваться стандартной схемой клиент <-> сервер?
не проще ли воспользоваться, во-первых, одним портом, во-вторых, сделать сервер одновременно и пишущим и читающим (ИМХО это намного легче, чем то что вы придумали=) )

дело в том что клиент сервер читающий и пишущий дает такой эффект что сообщения должны идти по очереди. и оба оппонента должны ввести свои сообщения и только после этого они увидят что прислал им другой конец. я же хотел сделать так чтобы любая сторона могла слать сообщения по нескольку штук подряд и чтобы их сразу можно было увидеть.... поэтому я решил разделить процессы чтения и записи... есть идеи лучше?
Спасибо сказали:
Аватара пользователя
Deo
Сообщения: 365
ОС: openSuse 12.3

Re: Сокеты

Сообщение Deo »

гм... насколько я помню свои опыты с Winsock восьмилетней давности, там была возможность асинхронной обработки событий вместо тупого постоянного слушания порта на предмет того, пришла ли инфа. Под Линь не информацией не располагаю, но учитывая то, что маздайные сокеты были слизаны, рекомендую поискать в этом направлении.
моё любимое облачко
Фхтагн! Мозг! Ням-ням! ~ Ктулху про Ленина
Спасибо сказали:
Аватара пользователя
MUTOgen
Сообщения: 343
Статус: i like the way you move
ОС: OpenSuse 11.1

Re: Сокеты

Сообщение MUTOgen »

Чтож... асинхронность это неплохо... потому что извращения с форками я выдумывал именно из-за тупого ожидания инфы в ридах... Возможно кто-то распологает более точной информацией по этой теме? Буду благодарен за ссылки на статьи или за название книг...
Спасибо сказали:
al.t
Сообщения: 52
ОС: Slackware

Re: Сокеты

Сообщение al.t »

man select?
Спасибо сказали:
Аватара пользователя
Rootlexx
Бывший модератор
Сообщения: 4471
Статус: GNU generation
ОС: Debian GNU/Linux

Re: Сокеты

Сообщение Rootlexx »

al.t писал(а):
20.08.2008 07:07
man select?

Лучше man poll (или epoll). Первый просто быстрее, а второй ещё и отлично масштабируется (здесь, правда, это не сильно нужно).
Спасибо сказали:
Аватара пользователя
RasenHerz
Сообщения: 1341
ОС: Arch Linux amd64

Re: Сокеты

Сообщение RasenHerz »

используйте очереди сообщений. реализовать можно даже начинающему программисту(простейший вариант - однонапраленный список, отсутствие сортировки по приоритету).
можно попробовать создать поток который будет по истечению тайм-аута просыпаться и проверять очередь на наличие новых сообщений/пакетов/и т.д и если в ней что-то есть, то будет предпринимать нужные вам действия.
Спасибо сказали: