Все технические форумы на одном сайте Удобный поиск информации с популярных форумов в одном месте
Вопрос: Клиент-серверное приложение на сокетах

всем привет.
Пытаюсь написать свой первый Клиент-сервер на WinForms.

Пока успехом не пахнет если есть минутка глянте.
КЛИЕНТ
Код C#
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
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
 
namespace ClientDots
{
    public partial class Form1 : Form
    {
        private string wServerIP; //объявили строковую переменную IP сервера
        const int SERVERPORT = 139;
        public Thread thread_receive_client;
 
        TcpClient tcpClient; // объявили переменную класса TCPClient
        TcpListener tcpListener;// объявили переменную класса TcpListener
        Socket soTcpServer; // объявили переменную класса Socket
 
        NetworkStream clientSockStream; //объявили экземпляр класса NetworkStream для клиента 
 
 
        public Form1()
        {
            InitializeComponent();
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
 
            wServerIP = "192.168.0.102"; //метод принимает значение IP адреса сервера
            byte[] buf = new byte[1]; //объявили массив на 1 байт который будет принимать данные
 
            try
            {
                thread_receive_client = new Thread(new ThreadStart(ThreadReceivingClient)); //определяем что в переменной thread_receive_client будет создан новый поток который реализует ДЕЛЕГАТ который принимает в качестве параметра закрытый метод ThreadReceivingClient
                thread_receive_client.Start(); //запустили поток
                MessageBox.Show("вы подключились");
            }
            catch (Exception ex)
            {
                MessageBox.Show("не удалось подключиться");
            }
        }
 
        private void ThreadReceivingClient() //метод для приема пакетов от сервера в потоке
        {
                byte[] buf = new byte[512]; //объявили буфер который будет принимать пакеты
  
                tcpClient = new TcpClient(wServerIP, SERVERPORT); //переменная класса TCPClient приняла два параметра IP и Port
                clientSockStream = tcpClient.GetStream(); //переменная класса NetworkStream открывает работу с потоком
         }
    }
}
СЕРВЕР
Код C#
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
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
 
namespace ServerDots
{
    public partial class Form1 : Form
    {
        public Thread thread_receive_server; //поток для сервера
        const int SERVERPORT = 139;
        TcpListener tcpListener;// объявили переменную класса TcpListener
        Socket soTcpServer; // объявили переменную класса Socket
        NetworkStream serverSockStream; //объявили экземпляр класса NetworkStream для сервера
 
        string wSerwerIP="";
 
        public Form1()
        {
            InitializeComponent();
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            thread_receive_server = new Thread(new ThreadStart(ThreadReceivingServer));
            thread_receive_server.Start();
        }
 
        private void ThreadReceivingServer() //этот метод используем в переменной thread_receive_server (выше на 5 строк)
        {
                byte[] buf = new byte[512]; // объявили массив байт 512 байт
                IPHostEntry localHostEntry = Dns.GetHostByName(Dns.GetHostName()); //Класс IPHostEntry связывает имя хоста службы DNS с массивом псевдонимов и массивом соответствующих им IP-адресов.
         
                tcpListener = new TcpListener(localHostEntry.AddressList[0], SERVERPORT);//переменная класса TcpListener. 1-ый параметр - задает список ip адресов, 2 - номер порта
 
            //ОШИБКА
                tcpListener.Start(); //метод Start() Запускает ожидание входящих запросов на подключение.
            //ОШИБКА
        }
    
ошибка в сервере в вызове метода Start

System.Net.Sockets.SocketException не обработано
ErrorCode=10048
HResult=-2147467259
Message=Обычно разрешается только одно использование адреса сокета (протокол/сетевой адрес/порт)
Кликните здесь для просмотра всего текста
NativeErrorCode=10048
Source=System
StackTrace:
в System.Net.Sockets.Socket.DoBind(EndPoint endPointSnapshot, SocketAddress socketAddress)
в System.Net.Sockets.Socket.Bind(EndPoint localEP)
в System.Net.Sockets.TcpListener.Start(Int32 backlog)
в System.Net.Sockets.TcpListener.Start()
в ServerDots.Form1.ThreadReceivingServer() в c:\users\baer\documents\visual studio 2015\Projects\ServerDots\ServerDots\Form1.cs:строка 45
в System.Threading.ThreadHelper.ThreadStart_Context(Object state)
в System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
в System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
в System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
в System.Threading.ThreadHelper.ThreadStart()
InnerException:


Подскажите что не так???
Ответ:
Сообщение от Exerion
У вас в тексте ошибки всё написано
тогда как может быть так. что в одной программе (код разбираю их рабочей программы) все работает а у меня нет???
Магия???
Спасибо за наводку попробую другой.
Вопрос: Клиент-серверное приложение на сокетах TCP. Умножение матрицы на матрицу

Здравствуйте!

Нужно создать клиент-серверное приложение, с помощью которого реализуется умножение матрицы на матрицу.
Массивы матриц задаются в клиенте, потом данные передаются серверу, на котором и происходит само вычисление (умножение).

Помогите, пожалуйста, разобраться. Никак не могу понять: как передать массивы с клиента серверу и после получить результат в клиенте.
Ответ: Спасибо большое за помощь!
Вопрос: Написание шлюза для приложения

Доброе времени суток. Возникла такая проблема. Есть приложение оно работает с базой данных. Приложение написано на java так же есть сервер linux где крутиться база этого приложения. Я хочу написать шлюз на с/c++ который будет принимать данные от приложения на шлюз шлюз будет общаться с базой. пересылать посланные запросы к базе и отправлять приложению ответы. Подскажите пожалуйста как можно написать подобного рода приложение ( шлюз ). Заранее благодарю за помощь. P.S. Не обязательно говорить как это сделать. Просто подскажите направление куда двигаться))))
Ответ: Создаешь подключение к БД, потом сокет на котором ждешь подключения от приложения. Когда приложение подключится, читаешь с сокета его запросы. Делаешь все, что нужно с БД, и отправляешь ответ приложению через сокет, который связывает тебя ним. В принципе, это все описано в любой статье по организации клиент-серверного приложения. Клиент у тебя уже есть. Тебе осталось написать "прокси"-сервер.
Вопрос: Как получить IP-адрес сервера из его сокета?

Всем добрый день. Помогите, пожалуйста, разобраться.
Есть клиент серверное приложение на сокетах. Серверная часть:

C#
1
2
3
4
5
6
7
8
9
            serverSocket = new Socket(AddressFamily.InterNetwork,
                          SocketType.Stream,
                          ProtocolType.Tcp);
 
            IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Any, 1000);
 
           
            serverSocket.Bind(ipEndPoint);
            serverSocket.Listen(10);
Как мне вывести на экран IP-адрес серверного сокета?

На
пишут такое:

C#
1
Console.WriteLine ("My local IpAddress is :" + IPAddress.Parse (((IPEndPoint)s.LocalEndPoint).Address.ToString ()) + "I am connected on port number " + ((IPEndPoint)s.LocalEndPoint).Port.ToString ());
Но у меня студия ругается на запись (IPEndPoint)s.

Заранее благодарю.
Ответ: IPAddress.Any указывает, что будут использоваться все доступные сетевые интерфейсы.
Для получения списка сетевых интерфейсов есть метод NetworkInterface.GetAllNetworkInterfaces()

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
foreach(NetworkInterface ni in NetworkInterface.GetAllNetworkInterfaces())
{
   if(ni.NetworkInterfaceType == NetworkInterfaceType.Wireless80211 || ni.NetworkInterfaceType == NetworkInterfaceType.Ethernet)
   {
       Console.WriteLine(ni.Name);
       foreach (UnicastIPAddressInformation ip in ni.GetIPProperties().UnicastAddresses)
       {
           if (ip.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
           {
               Console.WriteLine(ip.Address.ToString());
           }
       }
   }  
}
Вопрос: Исходник клиент-серверного на сокетах. Может есть у кого?

Добрый день! Может у кого есть клиент-серверное приложение на сокетах для отправки сообщения от клиента к серверу.

Delphi яп
Ответ: если Delphi, то
TServerSocket
TClientSocket
Вопрос: Как получить и передать информацию о пользователях Windows в приложении клиент-сервер?

Всем доброго времени суток. Возник вопрос по клиент-серверному приложению на сокетах, заключается он вот в чем:
Как на удаленном сервере получить информацию об учетных записях пользователей WINdows и групп этих пользователей?!
И как это все дело передать на клиент.

Запросы на сервере выполнять с клиента получилось, но вот даже сам ответ от сервера с какой- либо инфой как получить не знаю. Ткните плз куда соображать нужно?!

Добавлено через 10 часов 29 минут
спасибо, эти ветки уже курили. вопрос остается в вытягивании учетных записей и групп шарпом из винды.
Ответ:
C#
1
2
3
4
5
6
7
8
using System.Management;
 
SelectQuery query = new SelectQuery("Win32_UserAccount");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
foreach (ManagementObject envVar in searcher.Get())
{
     Console.WriteLine("Username : {0}", envVar["Name"]);
}
Вопрос: Пропадает сокет при длительном простое без обращения к нему

Hi!
Используется два серверных вебсокета, для двух Ciшных прог на портах 5555 и 9090 под управлением Debian 8.
Перед сервером стоит маршрутизатор с пробросом портов, и наружным статическим белым IP.
На сервере написана программуля (условно ПИНГАТОР) которая каждую минуту подключается к вебсокетам по адресу 85.175.ХХХ.ХХХ:5555 и 85.175.ХХХ.ХХХ:9090 с целью контроля работы и при необходимости рестарта вебсокета.

Проблема:
Если нет обращения к серверу снаружи (в течении 6 -12 часов), то сокеты хаотично перестают быть доступными (могут упасть оба, а может только один из них), при этом ПИНГАТОР нормально коннектиться к 85.175.ХХХ.ХХХ:5555 и 85.175.ХХХ.ХХХ:9090. Во внутренней сети порты доступны, сокеты отвечают как 85.175.ХХХ.ХХХ:5555 и 85.175.ХХХ.ХХХ:9090, так и по внутренним IP типа 193.168.1.ХХ.

То есть ПИНГАТОР знает что ничего не упало и все работает, а потому проги не перезапускает, но по факту это не так — сокеты снаружи не видны.

При ручном рестарте программуль сокеты снаружи становятся видимы.


В чем причина такого поведения и как с этим бороться?
Ответ: Я ставил прогу на разные серверы (в РФ, Украине, РБ), сделал так что сокет при обращении браузером на порт присылает месагу "Forbidden". Везде схема одинакова Роутер->Проброс->Сервер, везде картина одинакова.

Кстати да, чет я не подумал пробить на вшивость используя tcpdump.

Добавлено через 1 час 56 минут
Проходит
tcpdump -nnvvS src 31.41.48.211 and dst port 9090
Код
12:13:39.858656 IP (tos 0x0, ttl 58, id 29187, offset 0, flags [DF], proto TCP (6), length 60)
    31.41.48.211.45060 > 172.14.2.100.9090: Flags [S], cksum 0x07fd (correct), seq 2011745046, win 29200, options [mss 1360,sackOK,TS val 5093653 ecr 0,nop,wscale 7], length 0
Добавлено через 13 минут
Код
netstat -ntulp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:5355            0.0.0.0:*               LISTEN      440/systemd-resolve 
tcp        0      0 0.0.0.0:2000            0.0.0.0:*               LISTEN      699/asterisk        
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      518/nginx: master p 
tcp        0      0 0.0.0.0:5555            0.0.0.0:*               LISTEN      775/atda-bot        
tcp        0      0 0.0.0.0:1212            0.0.0.0:*               LISTEN      435/sshd            
tcp      129      0 0.0.0.0:9090            0.0.0.0:*               LISTEN      777/atda-loger-upda
Добавлено через 11 минут
Код
nmap localhost

Starting Nmap 7.40 ( https://nmap.org ) at 2018-06-20 13:13 EEST
Nmap scan report for localhost (127.0.0.1)
Host is up (0.000037s latency).
Other addresses for localhost (not scanned): ::1
Not shown: 994 closed ports
PORT     STATE SERVICE
80/tcp   open  http
81/tcp   open  hosts2-ns
2000/tcp open  cisco-sccp
5555/tcp open  freeciv
9000/tcp open  cslistener
9090/tcp open  zeus-admin
Вопрос: Работа с сокетами, основы клиент-серверного приложения

Нашел простой пример клиент-серверного приложения на C#:
Сервер:
Кликните здесь для просмотра всего текста
C#
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
// SocketServer.cs
using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
 
namespace SocketServer
{
    class Program
    {
        static void Main(string[] args)
        {
            // Устанавливаем для сокета локальную конечную точку
            IPHostEntry ipHost = Dns.GetHostEntry("localhost");
            IPAddress ipAddr = ipHost.AddressList[0];
            IPEndPoint ipEndPoint = new IPEndPoint(ipAddr, 11000);
 
            // Создаем сокет Tcp/Ip
            Socket sListener = new Socket(ipAddr.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
 
            // Назначаем сокет локальной конечной точке и слушаем входящие сокеты
            try
            {
                sListener.Bind(ipEndPoint);
                sListener.Listen(10);
 
                // Начинаем слушать соединения
                while (true)
                {
                    Console.WriteLine("Ожидаем соединение через порт {0}", ipEndPoint);
 
                    // Программа приостанавливается, ожидая входящее соединение
                    Socket handler = sListener.Accept();
                    string data = null;
 
                    // Мы дождались клиента, пытающегося с нами соединиться
                    
                    byte[] bytes = new byte[1024];
                    int bytesRec = handler.Receive(bytes);
                    
                    data += Encoding.UTF8.GetString(bytes, 0, bytesRec);
                    
                    // Показываем данные на консоли
                    Console.Write("Полученный текст: " + data + "\n\n");
                    
                    // Отправляем ответ клиенту\
                    string reply = "Спасибо за запрос в " + data.Length.ToString()
                            + " символов";
                    byte[] msg = Encoding.UTF8.GetBytes(reply);
                    handler.Send(msg);
 
                    if (data.IndexOf("<TheEnd>") > -1)
                    {
                        Console.WriteLine("Сервер завершил соединение с клиентом.");
                        break;
                    }
                    
                    handler.Shutdown(SocketShutdown.Both);
                    handler.Close();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
            finally
            {
                Console.ReadLine();
            }
        }
    }
}

Клиент:
Кликните здесь для просмотра всего текста
C#
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
// SocketClient.cs
using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
 
namespace SocketClient
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                SendMessageFromSocket(11000);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
            finally
            {
                Console.ReadLine();
            }
        }
 
        static void SendMessageFromSocket(int port)
        {
            // Буфер для входящих данных
            byte[] bytes = new byte[1024];
 
            // Соединяемся с удаленным устройством
            
            // Устанавливаем удаленную точку для сокета
            IPHostEntry ipHost = Dns.GetHostEntry("localhost");
            IPAddress ipAddr = ipHost.AddressList[0];
            IPEndPoint ipEndPoint = new IPEndPoint(ipAddr, port);
            
            Socket sender = new Socket(ipAddr.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
            
            // Соединяем сокет с удаленной точкой
            sender.Connect(ipEndPoint);
 
            Console.Write("Введите сообщение: ");
            string message = Console.ReadLine();
 
            Console.WriteLine("Сокет соединяется с {0} ", sender.RemoteEndPoint.ToString());
            byte[] msg = Encoding.UTF8.GetBytes(message);
            
            // Отправляем данные через сокет
            int bytesSent = sender.Send(msg);
            
            // Получаем ответ от сервера
            int bytesRec = sender.Receive(bytes);
            
            Console.WriteLine("\nОтвет от сервера: {0}\n\n", Encoding.UTF8.GetString(bytes, 0, bytesRec));
 
            // Используем рекурсию для неоднократного вызова SendMessageFromSocket()
            if (message.IndexOf("<TheEnd>") == -1)
                SendMessageFromSocket(port);
            
            // Освобождаем сокет
            sender.Shutdown(SocketShutdown.Both);
            sender.Close();
        }
    }
}

Результат:
Кликните здесь для просмотра всего текста


Ссылка на источник:

Локально все работает, теперь я хочу чтобы в роли сервера был мой настольный компьютер, а в роли клиента мой ноутбук, или любой другой компьютер подключенный к интернету.
Подскажите какие изменения необходимо внести в исходный код этих файлов, чтоб все заработало. На обоих системах стоит Visual Studio.
Ответ: Storm23, теперь такое исключение:
Подключение не установлено, т.к. конечный компьютер отверг запрос на подключение
Да у меня стоит роутер, сейчас попробую его отключить и подключить напрямую кабель.

Добавлено через 6 минут
Отлично, есть результат!
Все заработало с моим DDNS, осталось теперь только роутер настроить.
---
Теперь по другому вопросу, если я хочу, чтобы клиентские приложения соединялись с моим компьютером, то как мне указать им IP который у меня постоянно меняется? Первая мысль которая мне пришла, это в приложении-сервер прописать обновление текстового файла в папке Dropbox в который прописывается текущий IP. Приложения-клиенты первым делом просматривают этот файл (у dropbox при обновлении файла, ссылка не меняется) и пытаются подключиться по указанному в нем IP.
Вопрос: Не работает чат на сокетах

Привет. Есть чат на сокетах но, при попытке коннекта программа просто зависает. Уже окончательно запутался. Прошу помощи у форумчан.
Весь код ниже + ссылка на прогу
Program.cs
Кликните здесь для просмотра всего текста

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
 
namespace oneProject
{
    static class Program
    {
        /// <summary>
        /// Главная точка входа для приложения.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new oneProject.WindowSettings());
            Application.Run(new oneProject.MainChat());
        }
    }
}


Form1 (Настройка)
Кликните здесь для просмотра всего текста
C#
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
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Net;
using System.Net.Sockets;
 
namespace oneProject
{
    public partial class WindowSettings : Form
    {
        Thread WaitingForConnecting;
        public WindowSettings()
        {
            InitializeComponent();
            // Назначаем потоку имя ф-ции
            WaitingForConnecting = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(SocketWorker.CreateSocket));
            IPAdress.Text = GetLocalIP();
        }
 
        // Указывает на тип приложения
        private static bool AppCheckedTypeServer = true;
        // Обработчик таймера
        private void UpdateForm_Tick(object sender, EventArgs e)
        {
            // Если подключились - закрываем окно настроек
            if (SocketWorker.IsConnected)
            {
                try
                {
                    // Пытаемся завершить поток подключений
                    WaitingForConnecting.Abort();
                }
                catch { }
                // Закрываем окно настроек
                this.Close();
            }
            if (ServerRadio.Checked)
            {
                // Блокируем поле ввода IP-адреса
                IPAdress.Enabled = false;
                AppCheckedTypeServer = true;
            }
            else
            {
                AppCheckedTypeServer = false;
                IPAdress.Enabled = true;
            }
        }
 
        //функция возвращает айпи
        private string GetLocalIP()
        {
            IPHostEntry host;
            host = Dns.GetHostEntry(Dns.GetHostName());
            foreach (IPAddress ip in host.AddressList)
            {
                if (ip.AddressFamily == AddressFamily.InterNetwork)
                {
                    return ip.ToString();
                }
            }
            return "127.0.0.1";
        }
 
        private void StartChat_Click(object sender, EventArgs e)
        {
            // Блокируем кнопку от повторного нажатия
            StartChat.Enabled = false;
 
            // Настраиваем основной игровой объект
            Worker.CreateGameObject(AppCheckedTypeServer, ChatNick.Text);   
            // Запускаем поток подключения
            if (AppCheckedTypeServer)
            {
                // 0.0.0.0 -для прослушки внешней сети, не используйте 127.0.0.1 или localhost!
                WaitingForConnecting.Start(new Object[] { "0.0.0.0", "12123", AppCheckedTypeServer });
            }
            else
            {
                // 12123 –порт подключения
                WaitingForConnecting.Start(new Object[] { IPAdress.Text.ToString(), "12123", AppCheckedTypeServer });
            }
        }
 
        private void IPAdress_TextChanged(object sender, EventArgs e)
        {
            IPAdress.Text = GetLocalIP();
        }
    }
}


MainChat (сам чат)
Кликните здесь для просмотра всего текста
C#
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
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
 
namespace oneProject
{
    public partial class MainChat : Form
    {
        public MainChat()
        {
            InitializeComponent();
            // Создаем новый поток, указываем на ф-цию получения сообщений в классе Worker
            WaitingForMessage = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(Worker.GetMessages));
            // Запускаем, в параметрах передаем листбокс (история чата)
            WaitingForMessage.Start(new Object[] { ChatHistory });
        }
 
        // Обработчик отправки сообщения (кнопки)
        private void Send_Click(object sender, EventArgs e)
        {
            if (Worker.GlobalAppObject.ApplicationTypeProp == AppCore.AppType.Server)
            {
                // Посылаем клиенту новое сообщение
                SocketWorker.SendDataToClient(ChatText.Text, Worker.GlobalAppObject.ChatNickProp);
            }
            else
            {
                SocketWorker.SendDataToServer(ChatText.Text, Worker.GlobalAppObject.ChatNickProp);
            }
            // Добавляем в историю свое же сообщение + ник + время написания
            ChatHistory.Items.Add(DateTime.Now.ToShortTimeString() + " " + Worker.GlobalAppObject.ChatNickProp + ": " + ChatText.Text.ToString());
            // Автопрокрутка истории чата
            ChatHistory.TopIndex = ChatHistory.Items.Count - 1;
            // Убираем текст из поля ввода
            ChatText.Text = "";
        }
    }
}


AppCore
Кликните здесь для просмотра всего текста
C#
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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace oneProject
{
    class AppCore
    {
        // Тип приложения --------------------------------------------
        public enum AppType { Server, Client }
        private AppType ApplicationType;
        public AppType ApplicationTypeProp
        {
            get { return ApplicationType; }
            set { ApplicationType = value; }
        }
        // Ник в чате -----------------------------------------------
        private string ChatNick = "BadUser";
        public string ChatNickProp
        {
            get { return ChatNick; }
            set { ChatNick = value; }
        }
        // ----------------------------------------------------------
    }
}

Ссылка
Кликните здесь для просмотра всего текста
Ответ: класс SocketWorker
Кликните здесь для просмотра всего текста
C#
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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets; // Для работы с сокетами нужно подключить это пространство имен
using System.Text;
using System.Windows.Forms;
 
 
namespace oneProject
{
    class SocketWorker
    {
        // ----------------------------------------------------------------------
        private static IPHostEntry ipHost; // Класс для сведений об адресе веб-узла
        private static IPAddress ipAddr; // Предоставляет IP-адрес
        private static IPEndPoint ipEndPoint; // Локальная конечная точка
 
        private static Socket Server; // Создаем объект сокета-сервера
        private static Socket Client; // Создаем объект сокета-клиента
        private static Socket Handler; // Создаем объект вспомогательного сокета
        // ----------------------------------------------------------------------
        // Деструктор
        ~SocketWorker()
        {
            // Вместо проверки сокетов на подключение, просто используем блок try-catch
            try
            {
                // Сразу обрываем соединения
                Server.Shutdown(SocketShutdown.Both);
                // А потом закрываем сокет!
                Server.Close();
 
                Client.Shutdown(SocketShutdown.Both);
                Client.Close();
 
                Handler.Shutdown(SocketShutdown.Both);
                Handler.Close();
            }
            catch { }
        }
        // ----------------------------------------------------------------------
        // Создание сокета
        public static bool IsConnected = false;
        public static void CreateSocket(Object obj)
        {
            Object[] TempObject = (Object[])obj;
            // IP-адрес сервера, для подключения
            string HostName = (string)TempObject[0];
            // Порт подключения
            string Port = (string)TempObject[1];
            bool ServerApp = (bool)TempObject[2];
 
            // Разрешает DNS-имя узла или IP-адрес в экземпляр IPHostEntry.
           // ipHost = Dns.GetHostEntry(HostName);
            ipHost = Dns.Resolve(HostName);
            // Получаем из списка адресов первый (адресов может быть много)
            ipAddr = ipHost.AddressList[0];
            // Создаем конечную локальную точку подключения на каком-то порту
            ipEndPoint = new IPEndPoint(ipAddr, int.Parse(Port));
 
            if (!ServerApp)
            {
                try
                {
                    // Создаем сокет на текущей машине
                    Client = new Socket(AddressFamily.InterNetwork,
                    SocketType.Stream, ProtocolType.Tcp);
                    while (true)
                    {
                        // Пытаемся подключиться к удаленной точке
                        Client.Connect(ipEndPoint);
                        if (Client.Connected)
                            IsConnected = true;
                        break;
                    }
                }
                catch (SocketException error)
                {
                    // 10061 - порт подключения занят/закрыт
                    if (error.ErrorCode == 10061)
                    {
                        MessageBox.Show("Порт подключения закрыт!");
                        Application.Exit();
                    }
                }
            }
            else
            {
                try
                {
 
                    // Создаем сокет сервера на текущей машине
                    Server = new Socket(AddressFamily.InterNetwork,
                    SocketType.Stream, ProtocolType.Tcp);
                }
                catch (SocketException error)
                {
                    // 10061 - порт подключения занят/закрыт
                    if (error.ErrorCode == 10061)
                    {
                        MessageBox.Show("Порт подключения закрыт!");
                        Application.Exit();
                    }
                }
 
                // Ждем подключений
                try
                {
                    // Связываем удаленную точку с сокетом
                    Server.Bind(ipEndPoint);
                    // Не более 10 подключения на сокет
                    Server.Listen(10);
 
                    // Начинаем "прослушивать" подключения
                    while (true)
                    {
                        Handler = Server.Accept();
                        if (Handler.Connected)
                            IsConnected = true;
                        break;
                    }
                }
                catch
                {
                    throw new Exception("Проблемы с подключением");
                }
            }
        }
        // ----------------------------------------------------------------------
        // Получение данных от сервера
        public static string GetDataFromServer()
        {
            string GetInformation = "";
 
            // Создаем пустое «хранилище» байтов, куда будем получать информацию
            byte[] GetBytes = new byte[1024];
            int BytesRec = Client.Receive(GetBytes);
 
            // Переводим из массива битов в строку
            GetInformation += Encoding.Unicode.GetString(GetBytes, 0, BytesRec);
 
            return GetInformation;
        }
        // ----------------------------------------------------------------------
        // Получение информации от клиента
        public static string GetDataFromClient()
        {
            string GetInformation = "";
 
            byte[] GetBytes = new byte[1024];
            int BytesRec = Handler.Receive(GetBytes);
 
            GetInformation += Encoding.Unicode.GetString(GetBytes, 0, BytesRec);
 
            return GetInformation;
        }
        // ----------------------------------------------------------------------
        // Отправка информации на сервер
        public static void SendDataToServer(string Data, string Name)
        {
            // Используем unicode, чтобы не было проблем с кодировкой, при приеме информации
            byte[] SendMsg = Encoding.Unicode.GetBytes(Name + " : " + Data);
            Client.Send(SendMsg);
        }
        // ----------------------------------------------------------------------
        // Отправка информации на клиент
        public static void SendDataToClient(string Data, string Name)
        {
            byte[] SendMsg = Encoding.Unicode.GetBytes(Name + " : " + Data);
            Handler.Send(SendMsg);
        }
        // ----------------------------------------------------------------------
    }
}


класс Worker
Кликните здесь для просмотра всего текста
C#
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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
 
namespace oneProject
{
    class Worker
    {
        // Глобальный объект, характеризирующий персону в чате --------------------
        public static AppCore GlobalAppObject;
        // Настраивает объект выше
        public static void CreateGameObject(bool IsServer, string ChatNick)
        {
            GlobalAppObject = new AppCore();
            // Назначаем ник
            GlobalAppObject.ChatNickProp = ChatNick;
 
            // Тип приложения
            if (IsServer)
            {
                GlobalAppObject.ApplicationTypeProp = AppCore.AppType.Server;
            }
            else
            {
                GlobalAppObject.ApplicationTypeProp = AppCore.AppType.Client;
            }
        }
        // Ф-ция, работающая в новом потоке: получение новых сообщенй -------------
        public static void GetMessages(Object obj)
        {
            // Получаем объект истории чата (лист бокс)
            Object[] Temp = (Object[])obj;
            System.Windows.Forms.ListBox ChatListBox =
            (System.Windows.Forms.ListBox)Temp[0];
 
            // В бесконечном цикле получаем сообщения
            while (true)
            {
                // Ставим паузу, чтобы на время освобождать порт для отправки сообщений
                Thread.Sleep(50);
                if (GlobalAppObject.ApplicationTypeProp == AppCore.AppType.Server)
                {
                    try
                    {
                        // Получаем сообщение от клиента
                        string Message = SocketWorker.GetDataFromClient();
                        // Добавляем в историю + текущее время
                        ChatListBox.Items.Add(DateTime.Now.ToShortTimeString() + " " + Message);
                        // Автопрокрутка списка
                        ChatListBox.TopIndex = ChatListBox.Items.Count - 1;
                    }
                    catch { }
                }
                else
                {
                    try
                    {
                        string Message = SocketWorker.GetDataFromServer();
                        ChatListBox.Items.Add(DateTime.Now.ToShortTimeString() + " " + Message);
                        ChatListBox.TopIndex = ChatListBox.Items.Count - 1;
                    }
                    catch { }
                }
            }
        }
        // -----------------------------------------------------------------------
    }
}


Проект -
Кликните здесь для просмотра всего текста
Вопрос: Fork приложения на сетевом диске

Хз в тот ли раздел пишу - модеры поправьте, если что.
Суть такая, есть приложение в виде одного екзешника/бинарника весом под 200Мб. Приложение лежит на сетевом диске откуда и запускается юзверями. Естесно это приводит к тому, что приложение скачивается с сетевого диска. И все бы ничего, да вот только приложение при своей работе активно форкается, а это уже приводит к существенным сетевым нагрузкам и увеличивает время работы.
Приложение написано на С++/Qt, проблема актуальна как для винды так и для линукса. Есть ли какой-нибудь способ/механизм "объяснить" приложению/системе, что не обязательно при каждом форке качать копию по сети? :-?
Ответ:
Цитата Олег М @
Никакой аналогии там нет. Fork копирует существующий процесс, CreateProcess создает новый, с нуля. Соответственно, требуется загрузка файла

Проблема в таргеттинге. Т.е. в семантике.
Форк не копирует родительский процесс, а разветвляет его с созданием нового процесса.
Вот вам простой пример
    /*Тут куча инклюдов, опускаем*/
    #define MYPORT 3490     /* Порт, на который будет идти соединение*/
    #define BACKLOG 10 /* Сколько подключений может быть в очереди */
    int main()
       {
    int sd, newsd; /* Слушаем на сокете sd, новое подключение на сокете newsd */
    struct sockaddr_in my_addr;/* Серверная адресная информация */
    struct sockaddr_in their_addr;  /* Адресная информация запрашивающей стороны (клиента) */
    int sin_size;
    /* Создаем  Интернет-сокет, ориентированный на соединение*/
    if ((sd = socket (AF_INET, SOCK_STREAM, 0)) == -1)
    {perror ("socket");exit (1); }
    my_addr.sin_family = AF_INET;   /* В порядке байтов хоста */
    my_addr.sin_port = htons (MYPORT);/* short, в порядке байтов сети */
    /* Авто-заполнение IP-адресом серверного сетевого интерфейса */
    my_addr.sin_addr.s_addr = INADDR_ANY;
    bzero(&(my_addr.sin_zero), 8);/* Обнуляем остальную часть struct */
    /* Связываем только-что созданный сокет с его локальным адресом */
    if (bind(sd, (struct sockaddr *)&my_addr, sizeof (struct sockaddr)) == -1)
    {perror ("bind");exit (1);   }
    /* Организуем очередь прослушивания сети на порту MYPORT */
    if (listen (sd, BACKLOG) == -1)
    {perror ("listen");exit (1);}
    while(1) /* Главный цикл accept()*/
    {  
    sin_size = sizeof (struct sockaddr_in);
    if ((newsd = accept (sd, (struct sockaddr *)&their_addr, &sin_size)) == -1)
    {  perror ("accept"); continue; /* продолжаем прием*/   }
    /* Приняли запрос на соединение и принимаем решение ответить на него*/
    printf (" сервер: Принял соединение от %s\n ", inet_ntoa (their_addr.sin_addr));
    if(!fork())
    [B]{/* Мы находимся в дочернем порожденном процессе */
    close (sd); /* Закрываем дескриптор слушающего сокета, он потомку не нужен */
    /* Потомок наследует все файловые дескрипторы родителя, а значит, и newsd */
    /* Теперь таких сокетов два - в каждом процессе по одному */
    /* Шлем клиенту 14 байтов */
    if (send(newfd, " Привет, мир! \n", 14, 0) == -1)perror ("send");
    close(newsd);/* Закрываем сокет newsd  в порожденном процессе */
    exit (0);/* Завершаем передачу данных из процесса потомка */
    }   /* Здесь заканчивается текст процесса программы-потомка*/[/B]
    close (newsd);  /* Закрываем сокет newsd – родитель в нем не нуждается */
    while (waitpid (-1, NULL, WNOHANG) > 0);    /* Очищаем порожденные процессы */
    }/*Конец цикла accept()*/
    return 0;  
    }/* Завершаем процесс сервера */

Так вот, то что болдом - (Блин, болд не работает в срр) это и есть текст программы нового дочернего процесса. И - ВСЕ.
С вызова форка одновременно исполняются теперь два процесса одновременно. И говорить о копировании тут смысла нет. Ваще. Просто процесс-потомок наследует большую часть атрибутов своего родителя, и в частности, открытые файлы (порожденный процесс обладает копией дескрипторов файлов, открытых его родителем).
Однако порожденный процесс после вызова fork() с помощью функции exec() может запустить совершенно новый исполнимый файл, при этом его предыдущее "родительское" содержание в памяти заменяется текстом нового файла.
Так что вопрос в семантике форка. Это - не копирование, а разветвление. Потому и говорим, что Винда и никсы обладают совершенно разными подходами к вопросам запуска новых процессов.
Сообщение отредактировано: Oleg2004 -