Форум программистов, компьютерный форум, киберфорум
Java: Сети
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.86/7: Рейтинг темы: голосов - 7, средняя оценка - 4.86
 Аватар для waip
7 / 7 / 1
Регистрация: 27.05.2011
Сообщений: 297

Построение сетевых приложений

11.08.2013, 19:19. Показов 1363. Ответов 9
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всем привет. Недавно задался вопросом. Как же верно строить приложения.

Допустим наш клиент может на своем клиентском приложении нажать три кнопки. b1\b2\b3

Каждая кнопка это какое то действие связанное с сервером. Ну например:

b1 - обращение в базу данных
b2 - запись в текстовый файл на сервер
b3 - посылка сообщения в консоль.

Ок. Мы создаем сокет и слушаем что же нам присылает клиент. Вопрос... а что вообще посылать? Слова или сразу байты?
И как их потом понять?

допустим b1 посылает 4f

ок. я читаю первый байт и что потом? кидать его на условия мол
if(packet == 0x4f){
// todo code here
}

или есть какая то более интересная схема построения?
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
11.08.2013, 19:19
Ответы с готовыми решениями:

Программирование сетевых приложений
Добрый день, уважаемые форумчани! Ищу людей которые разрабатывали сетевые приложения под Windows. Нужна помощь и консультация. Буду рад...

Программирование сетевых приложений на C++
вот наткнулся на книгу "Программирование сетевых приложений на C++" Шмидт Д., Хьюстон С. но никак немогу найти где скачать ее, везде...

Программирование сетевых приложений
Очень хочу научиться писать нормальные клиент-сервера программы для linux на c++. Читал про сокеты в книжке "UNIX. Профессиональное...

9
Кандёхаем веселее!
 Аватар для MLPMan
296 / 330 / 76
Регистрация: 02.10.2012
Сообщений: 2,175
10.10.2013, 22:10
Цитата Сообщение от waip Посмотреть сообщение
или есть какая то более интересная схема построения?
Ну да, веб интерфейс, http запросы.
0
 Аватар для Matan!
1882 / 1016 / 228
Регистрация: 31.05.2013
Сообщений: 6,645
Записей в блоге: 6
13.10.2013, 22:42
Цитата Сообщение от waip Посмотреть сообщение
Вопрос... а что вообще посылать? Слова или сразу байты?
Как ты узнаешь,какие именно байты посылает клиент?Разве что написать функцию,которая будет возвращать код кнопки,а затем этот код использовать в качестве параметра,который пересылаем.
0
91 / 91 / 10
Регистрация: 18.05.2013
Сообщений: 265
14.10.2013, 10:00
2waip:
не стоит изобретать велосипед.
Есть устоявшиеся форматы - XML или там JSON.
Нажал кнопочку - создаем объект команды, упаковываем. посылаем на сервер. Там обратный процесс: 1) Распаковка, обработка, посылка ответа.
0
KeM6Pug}I{a
49 / 49 / 1
Регистрация: 23.08.2013
Сообщений: 202
14.10.2013, 15:50
Цитата Сообщение от waip Посмотреть сообщение
Всем привет. Недавно задался вопросом. Как же верно строить приложения.

Допустим наш клиент может на своем клиентском приложении нажать три кнопки. b1\b2\b3

Каждая кнопка это какое то действие связанное с сервером. Ну например:

b1 - обращение в базу данных
b2 - запись в текстовый файл на сервер
b3 - посылка сообщения в консоль.

Ок. Мы создаем сокет и слушаем что же нам присылает клиент. Вопрос... а что вообще посылать? Слова или сразу байты?
И как их потом понять?

допустим b1 посылает 4f

ок. я читаю первый байт и что потом? кидать его на условия мол
if(packet == 0x4f){
// todo code here
}

или есть какая то более интересная схема построения?
Написать свой хандлер (протокол).
Вот пример из моего кода:

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
package core.systems.handler;
 
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
 
 
 
 
 
import core.packets.clientpackets.CD_BY_NAME;
import core.packets.clientpackets.CD_BY_PATH;
import core.packets.clientpackets.CONNECT;
import core.packets.clientpackets.COPY_BY_NAME;
import core.packets.clientpackets.COPY_BY_PATH;
import core.packets.clientpackets.DELTREE_BY_NAME;
import core.packets.clientpackets.DELTREE_BY_PATH;
import core.packets.clientpackets.LOCK_BY_NAME;
import core.packets.clientpackets.LOCK_BY_PATH;
import core.packets.clientpackets.MD_BY_PATH;
import core.packets.clientpackets.MD_CURRENT;
import core.packets.clientpackets.MF_BY_NAME;
import core.packets.clientpackets.MF_BY_PATH;
import core.packets.clientpackets.MOVE_BY_NAME;
import core.packets.clientpackets.MOVE_BY_PATH;
import core.packets.clientpackets.PRINT;
import core.packets.clientpackets.Quit;
import core.packets.clientpackets.RD_BY_NAME;
import core.packets.clientpackets.RD_BY_PATH;
import core.packets.clientpackets.UNLOCK_BY_NAME;
import core.packets.clientpackets.UNLOCK_BY_PATH;
import core.packets.clientpackets.UnknownPacket;
import core.systems.User;
import core.systems.packets.request.RequestPackets;
 
public class RequestPacketHanlder implements IPacketHandler {
 
    @SuppressWarnings("incomplete-switch")
    @Override
    public RequestPackets handlePacket(ByteBuffer buf, User user) 
    {
        int id = buf.get() & 0xFF;
        RequestPackets packet = null;
        
        try
        {
            switch(user.getState())
            {
                case CONNECT:
                        switch(id)
                        {
                            case 0x01:
                                packet = new CONNECT();
                                break;
                            case 0x14:
                                packet = new Quit();
                            
                            default:
                                packet = new UnknownPacket();
                        }
                        break;
                        
                case CD:
                        switch(id)
                        {
                            case 0x01:
                                packet = new CD_BY_NAME();
                                break;
                            case 0x02:
                                packet = new CD_BY_PATH();
                                break;
                            case 0x03:
                                packet = new MF_BY_NAME();
                                break;
                            case 0x04:
                                packet = new MF_BY_PATH();
                                break;
                            case 0x05:
                                packet = new MD_CURRENT();
                                break;
                            case 0x06:
                                packet = new MD_BY_PATH();
                                break;
                            case 0x07:
                                packet = new RD_BY_NAME();
                                break;
                            case 0x08:
                                packet = new RD_BY_PATH();
                                break;
                            case 0x09:
                                packet = new DELTREE_BY_NAME();
                                break;
                            case 0x0A:
                                packet = new DELTREE_BY_PATH();
                                break;
                            case 0x0B:
                                packet = new COPY_BY_NAME();
                                break;
                            case 0x0C:
                                packet = new COPY_BY_PATH();
                                break;
                            case 0x0D:
                                packet = new MOVE_BY_NAME();
                                break;
                            case 0x0E:
                                packet = new MOVE_BY_PATH();
                                break;
                            case 0x0F:
                                packet = new LOCK_BY_NAME();
                                break;
                            case 0x10:
                                packet = new LOCK_BY_PATH();
                                break;
                            case 0x11:
                                packet = new UNLOCK_BY_NAME();
                                break;
                            case 0x12:
                                packet = new UNLOCK_BY_PATH();
                                break;
                            case 0x13:
                                packet = new PRINT();
                                break;
                            case 0x14:
                                packet = new Quit();
                                break;
                                
                            default:
                                packet = new UnknownPacket();
                        }
                        break;
 
            case ACCEPT_NAME:
                        switch(id)
                        {
                            case 0x01:
                                packet = new CD_BY_NAME();
                                break;
                            
                            case 0x02:
                                packet = new CD_BY_PATH();
                                break;
                                
                            case 0x14:
                                packet = new Quit();
                                break;
                                
                            default:
                                packet = new UnknownPacket();
                        }
                        break;
                
                
            case DISCONNECT:
                break;
            
            }
            
        }catch(BufferUnderflowException ex)
        {
            user.PendingClose();
        }
        
        return packet;
    }
 
}
Архитектура получаеться такая :
Мы читаем и пишем пакеты в одном потоке силектора.Пакеты каторые мы прочитали выполняем в пуле потоков.
Сами пакеты это то что в c++ называется функциональным объектом (или объектом запросом), эти пакеты обычно Runnable. В них описывается логика обработки запроса.
Вот например пакет из моей программки Virtual File System, которая удаляет папку:

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package core.packets.clientpackets;
 
import core.packets.serverpackets.Send;
import core.systems.File;
import core.systems.User;
import core.systems.packets.request.RequestPackets;
 
public class RD_BY_PATH extends RequestPackets
{
 
    @Override
    protected void readImpl() throws Exception 
    {
        path = readS();
    }
 
    @Override
    protected void runImpl() throws Exception 
    {
        File file = User.parsePath(path);
        
        if(getUser().deleteFileOrDir(file))
        {
            String st = file.getAbsolutePath();
                
            // < 10 > = "<UserName> удалил папку : <Path>"
            getUser().sendToAll(10, getUser().getUserName(), st);
            
            getUser().sendPacket(new Send(29));
        }
        else
        {
            // < 18 > : Неудалось удалить директорию
            getUser().sendPacket(new Send(18));
        }
    }
 
    private String path;
}
Добавлено через 1 минуту
Если хотите выложу исходники...
0
14.10.2013, 15:51

Не по теме:

Цитата Сообщение от MbICJIuTeJIb_u3 Посмотреть сообщение
Вот пример из моего кода:
Никогда больше не показывайте такой код! А то кто-то ни дай Бог решит такое повторить! И исходников не выкладывайте, приведенных switch уже более чем достаточно.

0
KeM6Pug}I{a
49 / 49 / 1
Регистрация: 23.08.2013
Сообщений: 202
14.10.2013, 16:01
Цитата Сообщение от MbICJIuTeJIb_u3 Посмотреть сообщение
Сами пакеты это то что в c++ называется функциональным объектом (или объектом запросом), эти пакеты обычно Runnable. В них описывается логика
При том нужно обеспечить синхронизацию , то есть что бы запросы выполнялись не асинхронно , а синхронно но при этом не терялась польза от много поточности. Для этого обычно пишут runnable-очереди:
вот моя реализация:

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
package core.systems.threads;
 
 
import java.util.ArrayDeque;
import java.util.Collection;
import java.util.Iterator;
import java.util.Queue;
import java.util.concurrent.atomic.AtomicInteger;
 
import org.apache.log4j.Logger;
 
 
 
public class ExecutableQueue<T extends Runnable> implements Queue<T>, Runnable
{
    private static final int NONE = 0;
    private static final int QUEUED = 1;
    private static final int RUNNING = 2;
    private final PacketExecutor _executor;
    private final Queue<T> _queue;
    private AtomicInteger _state = new AtomicInteger(NONE);
    
    @SuppressWarnings("unused")
    private static final Logger log = Logger.getLogger(ExecutableQueue.class);
 
    public ExecutableQueue(PacketExecutor executor)
    {
        _executor = executor;
        _queue = new ArrayDeque<T>();
    }
 
    @Override
    public void run()
    {
        while (_state.compareAndSet(QUEUED, RUNNING))
        {
            try
            {
                for (;;)
                {
                    final Runnable t = poll();
                    
                    
                    if (t == null)
                    {
                        break;
                    }
                    
                    t.run();
                }
            }
            finally
            {
                _state.compareAndSet(RUNNING, NONE);
            }
        }
    }
 
    @Override
    public int size()
    {
        return _queue.size();
    }
 
    @Override
    public boolean isEmpty()
    {
        synchronized (_executor) 
        {
             return _queue.isEmpty();
        }
    }
 
    @Override
    public boolean contains(Object o)
    {
        throw new UnsupportedOperationException();
    }
 
    @Override
    public Iterator<T> iterator()
    {
        throw new UnsupportedOperationException();
    }
 
    @Override
    public Object[] toArray()
    {
        throw new UnsupportedOperationException();
    }
 
    @Override
    public <E> E[] toArray(E[] a)
    {
        throw new UnsupportedOperationException();
    }
 
    @Override
    public boolean remove(Object o)
    {
        throw new UnsupportedOperationException();
    }
 
    @Override
    public boolean containsAll(Collection<?> c)
    {
        throw new UnsupportedOperationException();
    }
 
    @Override
    public boolean addAll(Collection<? extends T> c)
    {
        throw new UnsupportedOperationException();
    }
 
    @Override
    public boolean removeAll(Collection<?> c)
    {
        throw new UnsupportedOperationException();
    }
 
    @Override
    public boolean retainAll(Collection<?> c)
    {
        throw new UnsupportedOperationException();
    }
 
    @Override
    public void clear()
    {
        synchronized (_queue)
        {
            _queue.clear();
        }
    }
 
    @Override
    public boolean add(T e)
    {
        synchronized (_queue)
        {
            if (!_queue.add(e))
            {
                return false;
            }
        }
 
        if (_state.getAndSet(QUEUED) == NONE)
        {
            _executor.execute(this);
        }
 
        return true;
    }
 
    @Override
    public boolean offer(T e)
    {
        synchronized (_queue)
        {
            return _queue.offer(e);
        }
    }
 
    @Override
    public T remove()
    {
        synchronized (_queue)
        {
            return _queue.remove();
        }
    }
 
    @Override
    public T poll()
    {
        synchronized (_queue)
        {
            return _queue.poll();
        }
    }
 
    @Override
    public T element()
    {
        synchronized (_queue)
        {
            return _queue.element();
        }
    }
 
    @Override
    public T peek()
    {
        synchronized (_queue)
        {
            return _queue.peek();
        }
    }
}
Добавлено через 1 минуту
Цитата Сообщение от Skipy Посмотреть сообщение
Никогда больше не показывайте такой код! А то кто-то ни дай Бог решит такое повторить! И исходников не выкладывайте, приведенных switch уже более чем достаточно.

Не по теме:

А что с ним не так? Рад услышать критику или советы.

0
 Аватар для Skipy
2000 / 1427 / 92
Регистрация: 25.11.2010
Сообщений: 3,611
14.10.2013, 16:13
Цитата Сообщение от MbICJIuTeJIb_u3 Посмотреть сообщение
А что с ним не так? Рад услышать критику или советы.
Вы создаете по объекту на каждый пакет. При большом количестве пакетов это серьезная нагрузка на сборщик мусора. При том что достаточно сделать эти классы thread-safe - и можно будет держать по одному экземпляру. Более того, в этом случае можно будет и от switch избавиться - делаете Map, в котором по ключу, соответствующему аргументу switch, лежит нужный обработчик. Если надо быстро - делаете массив вместо Map, но там придется немного повозиться с отсутствующими индексами.
0
 Аватар для mutagen
2587 / 2260 / 257
Регистрация: 14.09.2011
Сообщений: 5,185
Записей в блоге: 18
14.10.2013, 16:16
Цитата Сообщение от MbICJIuTeJIb_u3 Посмотреть сообщение
Рад услышать критику или советы.
подчеркушки глаза режут, кемелкейса хочется
0
KeM6Pug}I{a
49 / 49 / 1
Регистрация: 23.08.2013
Сообщений: 202
14.10.2013, 17:00
Цитата Сообщение от Skipy Посмотреть сообщение
Вы создаете по объекту на каждый пакет. При большом количестве пакетов это серьезная нагрузка на сборщик мусора. При том что достаточно сделать эти классы thread-safe - и можно будет держать по одному экземпляру. Более того, в этом случае можно будет и от switch избавиться - делаете Map, в котором по ключу, соответствующему аргументу switch, лежит нужный обработчик. Если надо быстро - делаете массив вместо Map, но там придется немного повозиться с отсутствующими индексами.
Вы хотите сказать что например я от 40 клиентов буду читать в один и тот же пакет? А как насчет того что каждый клиент отправляет разные данные и это все обрабатывается в 10 потоках ? Как вы представляете себе сделать этот класс Thread-Safe?

Добавлено через 2 минуты
Цитата Сообщение от MbICJIuTeJIb_u3 Посмотреть сообщение
Как вы представляете себе сделать этот класс Thread-Safe?
Вообще этот класс и так thread-safe , просто этот thread-safe реализован внутри.

Добавлено через 13 минут
Помойму вы не поняли логику приложения.
Все пакеты читаются (из ByteBuffr'a парсятся и помещаются в очередь , у каждого юзера своя Runnable очередь),
помещаются в Runnable очередь так :
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  @Override
    public boolean add(T e)
    {
        synchronized (_queue)
        {
            if (!_queue.add(e))
            {
                return false;
            }
        }
 
        if (_state.getAndSet(QUEUED) == NONE)
        {
            _executor.execute(this);
        }
 
        return true;
    }
То есть если Runnable очередь этого юзера УЖЕ обрабатывается потоком из пула , то новый пакет просто добавляется в очередь и на обрабтку ,иначе мы задаем таск пулу (или поток-менеджеру) что надо обработать текущую очередь. Тем самым пакеты обрабатываются синхронно и это обеспечивает использования ядер процессора на полную.

Когда мы парсим пакет то в него читается информация в методе readImpl который вызывается в селекторе , а не в пуле (то есть когда мы читаем данные). Когда пакет обрабатывается пулом то вызывается метод runImpl где описанна логика обработки пакета. Поэтому тут использование синглетного класса не возможно.

Добавлено через 4 минуты
Цитата Сообщение от Skipy Посмотреть сообщение
. Если надо быстро - делаете массив вместо Map, но там придется немного повозиться с отсутствующими индексами.
Об этом я думал, но только запихнуть в массив объекты типа Class и через них вызывать новый инстанс, но решил воспользоваться старым добрым switch. Тем более добавлять новые пакеты так намного легче чем искать этот массив и добавлять в него новый объект Class.

Добавлено через 4 минуты
И да пролема ещё в том что User не может отправить пакет например md_by_name когда его состояние disconnect или же connect. Если это все запихнуть в массив то как это все потом проверять и хандлить?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
14.10.2013, 17:00
Помогаю со студенческими работами здесь

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

Литература по написанию сетевых приложений
Здравствуйте! Ребята подскажите пожалуйста, литературу по написанию сетевых приложений. К примеру мне нужно написать программу типа...

MS Visual C++ 2010 программирование сетевых приложений
Всем привет! Так как я в С++ еще мягко говоря двоечник, не могли бы вы мне подсказать, какие существуют возможности в С++ для написания...

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

Ищу книги Шмидт, Хьюстон Программирование сетевых приложений на C++
Здравствуйте! В электронном виде ищу книги &quot;Шмидт, Хьюстон Программирование сетевых приложений на C++&quot; (1 и 2 том) на русском языке....


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
10
Ответ Создать тему
Новые блоги и статьи
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост. Налог на собак: https:/ / **********/ gallery/ V06K53e Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf Пост отсюда. . .
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Нашел на реддите интересную статью под названием Anyone know where to get a free Desktop or Laptop? Ниже её машинный перевод. После долгих разбирательств я наконец-то вернула себе. . .
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Рецензия / Мнение/ Перевод Нашел на реддите интересную статью под названием The Thinkpad X220 Tablet is the best budget school laptop period . Ниже её машинный перевод. Thinkpad X220 Tablet —. . .
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru