Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Unix консольный чат.  (Прочитано 7539 раз)
0 Пользователей и 2 Гостей смотрят эту тему.
IgnisFatuus
Постоялец

ru
Offline Offline

« : 21-09-2012 09:56 » 

И снова здравствуйте.

Как обычно за советом.

Решил немного поизвращаться и написал простенький чатик -

Сервер :
Код: (C++)

#include <iostream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
using namespace std;

int main() {
        int sock, listener;
            struct sockaddr_in addr;
            char buf[1024];
            int bytes_read;
            char message[1024];

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

            addr.sin_family = AF_INET;
            addr.sin_port = htons(3425);
            addr.sin_addr.s_addr = htonl(INADDR_ANY);
            if(bind(listener, (struct sockaddr *)&addr, sizeof(addr)) < 0)
            {
                perror("bind");
                exit(2);
            }

            listen(listener, 1);


            fd_set rfds;
                struct timeval tv;
                int retval;




        sock = accept(listener, NULL, NULL);
        if(sock < 0)
        {
            perror("accept");
            exit(3);
        }
        cerr << "accepted\n";

            while(1)
            {

                FD_ZERO(&rfds);
                        FD_SET(sock, &rfds);
                        FD_SET(0, &rfds);
                        tv.tv_sec = 5;
                        tv.tv_usec=0;


                retval= select(sock + 1,&rfds,0,0,0);
                if(retval == 0)
                        {
                                cerr << "timeout\n";
                        }
                        else if(retval < 0)
                        {
                                cerr << "error\n";
                        }
                        else
                        {
                                if(FD_ISSET(sock,&rfds))
                                {


                                        bytes_read = recv(sock, buf, 1024, 0);
                                        if(bytes_read <= 0) break;
                                        cout << "Client says:" << buf << endl;
                                        for (int i =0; i <1024; i++)
                                        {
                                                buf[i] = 0;
                                        }
                                }
                                if(FD_ISSET(0,&rfds))
                                {

                                        read(0,message, sizeof(message));

                                         send(sock, message, sizeof(message), 0);
                                         for (int j=0;j <1024; j++)
                                                {
                                                 message[j] = 0;
                                                }
                                }
                        }
            }

            close(sock);

        return 0;
}
 

и клиент :

Код: (C++)





#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
using namespace std;

char message[1024];
char buf[1024];




int main()
{
        int sock;
        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);
        }

        fd_set rfds;
        struct timeval tv;
        int retval;


        while(1)
        {

                FD_ZERO(&rfds);
                FD_SET(sock, &rfds);
                FD_SET(0, &rfds);
                tv.tv_sec = 5;
                tv.tv_usec=0;


                retval= select(sock + 1,&rfds,0,0,0);
                if(retval == 0)
                {
                        cerr << "timeout\n";
                }
                else if(retval < 0)
                {
                        cerr << "error\n";
                }
                else
                {
                        if(FD_ISSET(sock,&rfds))
                        {
                                int bytes = recv(sock, buf, sizeof(buf), 0);
                                buf[bytes] = 0;
                                printf("Server say : %s\n",buf);
                                for(int i=0; i< 1024; i++)
                                {
                                        buf[i] =0;
                                }
                        }
                        if(FD_ISSET(0,&rfds))
                        {
                                read(0,message, sizeof(message));

                                if(!strcmp(message,"exit\n"))
                                        break;

                                if(!(message[0] == 0 && message[1] == 0 && message[2] == 0))
                                        send(sock, message, sizeof(message), 0);
                                for(int i=0; i< 1024; i++)
                                        {
                                        message[i] =0;
                                        }
                        }

                }
        }
        close(sock);

        return 0;
        }




 

Вопросы заключаются в следующем

 1) Что стоит поменять? Что доделать?
2) Слышал про такую вундервафлю как QT  - думаю - стоит ли наней делать ... интерфейс.
3) Можно ли как-то сюда добавить логи?
4. Не понял
5.  Ничего в голову не приходит, спрошу потом...

Записан
Вад
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #1 : 21-09-2012 10:43 » new

IgnisFatuus, а какова цель упражнений? Потому что, ведь, нет предела совершенству, а если делать чат ради чата, а не ради упражнений, то быстро кончится xmpp-движком или веб-приложением с аяксом и стилями (причём, одно другому, в общем-то, не мешает даже).
От цели зависит дальнейшее улучшение.

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

Что касается Qt (ты ведь его имел в виду, а не Quick Time?) - то что хочется сделать, UI? В Qt ведь вообще много всего, и обёртки для сокетов есть, и контейнеры, и прочее, и прочее. Если всё делать в рамках какого-то фреймворка - то надо возвращаться к цели: хочется решить задачу, или хочется её решать своим путём?

ЗЫ. Из кода как-то не очень понял, где собственно чат - может, проглядел, куда пользователь сообщения вводит?
« Последнее редактирование: 21-09-2012 10:48 от Вад » Записан
IgnisFatuus
Постоялец

ru
Offline Offline

« Ответ #2 : 21-09-2012 10:45 » 

оу... Забыл...
Обнуление буфера (buf && message) заменил на


! memset !

Вроде так лучше?

Добавлено через 11 минут и 1 секунду:
IgnisFatuus, а какова цель упражнений?

Цель.. Я сейчас работаю инженером-(тестировциком/программистом), тестирую исходники модулей, пишу мелкий софт под железки и тут мне пришлось столкнуться с необходимостью нолучше узнать .... сетевое программирование. И мне все это на столько понравилось, что я в серьез задумался о смене специализации после того как опыта наберусь.

Покумекал, решил сделать так - напишу чат. Простенький. Затем прикручу к нему что-нибудь. И еще, и еще.
Ну и соответственно опыт, понимание... Я больше прошу совета такого рода -

" Есть чат. Что делаешь - прикручиваешь к нему %name%, затем %name%.  После этого копаешься в %name% и изучешь его - сможешь запилить вундервафлю %name%".
 ну или как-то так. Я как обычно рад критике ) .
« Последнее редактирование: 21-09-2012 10:56 от IgnisFatuus » Записан
Вад
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #3 : 21-09-2012 11:20 » 

IgnisFatuus, а, ну, тогда я бы, всё-таки, структурировал код, как уже написал выше. Из вундер-вафель - для начала, как по мне, мультиканальность, база данных (можно взять простецкий sqlite) - чтобы можно было при подключении к чату получить историю последних сообщений, списки пользователей в сети, и так далее.
Предусмотреть обработку случая обрыва соединения и, как вариант, его автоматическое восстановление.

Только к сетям это всё уже мало отношения имеет: сеть - вот они сокеты, и всё. Если только возиться, смотреть, как принято подобные протоколы обмена сообщениями делать, и пробовать своё - ну, бинарные там протоколы или текстовые, как обрабатывать ошибки соединения, безопасно авторизовать пользователей, как преодолевать проблему большого числа пользователей на сервере, и т.п.
« Последнее редактирование: 21-09-2012 11:23 от Вад » Записан
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #4 : 21-09-2012 18:49 » 

IgnisFatuus, почитай Стивенсона - это классика: https://club.shelek.ru/viewfiles.php?id=39
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines