Форум программистов, компьютерный форум, киберфорум
C# Windows Forms
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.82/11: Рейтинг темы: голосов - 11, средняя оценка - 4.82
-1 / 0 / 0
Регистрация: 20.06.2016
Сообщений: 12

Потеря частей файла при передаче по TCP

14.08.2020, 13:33. Показов 2213. Ответов 8

Студворк — интернет-сервис помощи студентам
Здравствуйте уважаемый Форум, у меня в ходе написания собственного чата возникла проблема. Имеется сервер многопоточный и к нему могут подключиться только 2 клиента. При подключении клиента к серверу обработка каждого клиента(приём и отправка данных) происходят в отдельном потоке. Сам же клиент запускает отдельный поток по прослушке входящих данных. Вот в чем собственно проблема, я пытаюсь отправить изображение с клиента на клиент. Т.е сначала отправляются метаданные(тип и размер) а далее само изображение на сервер и там сохраняется, далее высылается целевому клиенту, и именно здесь появляется проблема. Когда первый клиент высылает изображение на сервер проблем нет, сервер его отлично сохраняет, но вот далее сервер отправляет целевому клиенту и тут проблема в том, что сервер отправляет файл полностью (просматривал используя длину потока файла и длина потока который был отправлен) но клиент принимает не совсем целый файл. Т.е если сервер разбивает файл на 1450 частей то клиент получает шде-то 1445-1448, хотя бывают случаи что получает файл целиком. Сижу уже с этим целую неделю никак не могу найти решение данной проблемы, просил бы вашей помощи спасибо.

Код сервера
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
public class Server
    {
        static TcpListener listener;
        private FileDetails fileData = new FileDetails();
        List<ClientObject> clients = new List<ClientObject>();
        public static object locker = new object();
        protected internal void AddConnection(ClientObject x)
        {
            if (clients.Count < 2)
            clients.Add(x);
        }
protected internal void BroadcastMessage(string msg, string id)
        {
            byte[] data = Encoding.UTF8.GetBytes(msg);
            foreach (ClientObject x in clients)
            {
                if (x.Id != id) x.stream.Write(data, 0, data.Length);
            }
        }
protected internal void SendPhoto(FileDetails fd, string fs, string id)
        {
            FileStream fstream = File.Open(fs, FileMode.Open, FileAccess.ReadWrite, FileShare.None);
            foreach (ClientObject x in clients)
            {
                if (x.Id != id)
                {
                    try
                    {
                        byte[] data = Encoding.UTF8.GetBytes(fs);
                        x.stream.Write(data, 0, data.Length);
                    }
                    catch
                    {
                        Console.WriteLine("Sending image notification error");
                    }
                    try
                    {
                        fileData.FILESIZE = fd.FILESIZE;
                        fileData.FILETYPE = fd.FILETYPE;
                        //Send metadata//
                        string json = JsonConvert.SerializeObject(fileData);
                        Console.WriteLine($"send metadata {json}");
                        byte[] bytes = Encoding.UTF8.GetBytes(json);
                        x.stream.Write(bytes, 0, bytes.Length);
                    }
                    catch
                    {
                        Console.WriteLine("Sending metadata error");
                    }
                    //Send Photo//
                    try
                    {
                        int i = 0;
                        byte[] bites = new byte[256];
                        int size = 0;
                        while ((size = fstream.Read(bites, 0, bites.Length)) > 0)
                        {
                            Console.WriteLine($"Sending {i} part of file");
                            x.stream.Write(bites, 0, size);
                            i++;
                        }
                        fstream.Close();
                        Console.WriteLine($"100% file sended");
                    }
                    catch
                    {
                        Console.WriteLine("Sending file error");
                    }
                }
            }
        }
protected internal void RemoveConnection(string id)
        {
            ClientObject tmp = clients.FirstOrDefault(c => c.Id == id);
            if (tmp != null) clients.Remove(tmp);
            Console.WriteLine($"Client has left the chat");
        }
protected internal void Disconnect()
        {
            listener.Stop();
            foreach (ClientObject t in clients) t.Close();
            Environment.Exit(0);
        }
protected internal void Listen()
        {
            try
            {
                listener = new TcpListener(IPAddress.Any, 8888);
                listener.Start();
                Console.WriteLine("Server is started");
                while (true)
                {
                    TcpClient tmp = listener.AcceptTcpClient();
                    ClientObject cobject = new ClientObject(tmp, this);
                    Thread t = new Thread(new ThreadStart(cobject.Process));
                    t.Start();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            finally
            {
                Disconnect();
            }
        }
    }
Код обработки каждого клиента, он же ClientObject
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
 public class ClientObject
    {
        [Serializable]
        public class FileDetails
        {
            public string FILETYPE = "";
            public string FILESIZE = "";
        }
        private static FileDetails fileDet = new FileDetails();
        protected internal string Id { get; set; }
        protected internal NetworkStream stream { get; set; }
        static TcpClient client;
        Server server;
        Random rnd = new Random();
        public ClientObject(TcpClient x, Server y)
        {
            server = y;
            client = x;
            Id = Guid.NewGuid().ToString();
            y.AddConnection(this);
        }
        private void GetFileDetails()
        {
            try
            {
                Byte[] receiveBytes = new Byte[256];
                do
                {
                    int bytes = stream.Read(receiveBytes, 0, receiveBytes.Length);
                }
                while (stream.DataAvailable);
                string json = Encoding.UTF8.GetString(receiveBytes);               
                fileDet = JsonConvert.DeserializeObject<FileDetails>(json);
            }
            catch (Exception ex)
            {
                Console.WriteLine("GetFileDetails Error in ClientObject class");
            }
        }
        public static int mark = 0;
        public void GetImage()
        {
            mark = rnd.Next(1000, 9999);
            FileStream fs = new FileStream($"image{mark}" + fileDet.FILETYPE, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);
            Byte[] receiveBytes = new Byte[256];            
            try
            {
                do
                {
                    int bytes = stream.Read(receiveBytes, 0, receiveBytes.Length);
                    fs.Write(receiveBytes, 0, bytes);
                }
                while (fs.Length != Convert.ToInt64(fileDet.FILESIZE));
                fs.Close();
            }
            catch (Exception eR)
            {
                Console.WriteLine(eR.ToString() + " GET IMAGE ERROR");
            }
        }
        private void SendPhoto()
        {
            server.SendPhoto(fileDet, $"image{mark}{fileDet.FILETYPE}", Id);
            Console.WriteLine("photo has sent");
        }
        public void Process()
        {
            try
            {
                stream = client.GetStream();
                string username = $"User{rnd.Next(500)}";
                Console.WriteLine(username + "connected :)");
                while (true)
                {
                    string servermsg = "";
                    string msg = GetMessage();
                    try
                    {
                        string output = new string(msg.Where(c => char.IsLetter(c) || char.IsDigit(c) || char.IsSymbol(c) || char.IsSeparator(c) || char.IsPunctuation(c)).ToArray());
                        if (output == "photo")
                        {
                            GetFileDetails();
                            servermsg = String.Format("{0}: {1}, {2}, {3}", username, output, "ok", fileDet.FILETYPE);
                            output = "";
                            Console.WriteLine(servermsg);
                            GetImage();
                            Console.WriteLine("Получен файл типа " + fileDet.FILETYPE + " имеющий размер " + fileDet.FILESIZE + " байт");
                            SendPhoto();
                        }
                        else
                        {
                            servermsg = String.Format("{0}: {1}", username, output);
                            Console.WriteLine(servermsg);
                            server.BroadcastMessage(msg, Id);
                        }
                    }
                    catch (Exception ex)
                    {
                        servermsg = String.Format("{0}: leave chat", username);
                        Console.WriteLine(servermsg);
                        break;
                    }
                } 
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Global Error! {ex.Message}");
            }
            finally
            {
                server.RemoveConnection(Id);
                Close();
            }
        }
        public string GetMessage()
        {
            byte[] data = new byte[256];
            StringBuilder sb = new StringBuilder();
            int bytes = 0;
            do
            {
                bytes = stream.Read(data, 0, data.Length);
                sb.Append(Encoding.UTF8.GetString(data));
            }
            while (stream.DataAvailable);
            return sb.ToString();
        }
        protected internal void Close()
        {
            if (stream != null) stream.Close();
            if (client != null) client.Close();
        }
    }
И собственно сам клиент, который подключается к серверу, но я покажу не весь код т.к остальное закомментировано на данный момент в связи с данной проблемой
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
        public Form1()
        {
            InitializeComponent();
            client = new TcpClient();
            client.Connect(ip, port);
            Thread t = new Thread(new ThreadStart(ReceiveMessage));
            t.Start();
            stream = client.GetStream();
        }
        public void ReceiveMessage()
        {
            while (true)
            {
                byte[] data = new byte[256];
                StringBuilder sb = new StringBuilder();
                int bytes = 0;
                do
                {
                    bytes = stream.Read(data, 0, data.Length);
                    sb.Append(Encoding.UTF8.GetString(data));
                }
                while (stream.DataAvailable);             
                gettedMessage = sb.ToString();
                string output = new string(gettedMessage.Where(c => char.IsLetter(c) || char.IsDigit(c) || char.IsSymbol(c) || char.IsSeparator(c) || char.IsPunctuation(c)).ToArray());
                if (output.Contains("image"))
                {
                    lock (locker)
                    {
                        GetFileDetails();
                        GetFile(output);
                        gettedMessage = "";
                        path = $"{output}";
                    }
                }
            }
        }
        private void GetFileDetails()
        {
            try
            {
                StringBuilder sb = new StringBuilder();
                byte[] receiveBytes = new byte[256];
                do
                {
                    int bytes = stream.Read(receiveBytes, 0, receiveBytes.Length);
                    sb.Append(Encoding.UTF8.GetString(receiveBytes));
                }
                while (stream.DataAvailable);
                int startindex = sb.ToString().IndexOf('{');
                int endindex = sb.ToString().IndexOf('}');
                string json = sb.ToString().Substring(startindex, endindex - startindex + 1);
                fileDet = JsonConvert.DeserializeObject<FileDetails>(json);
            }
            catch (Exception ex)
            {
                altoTextBox1.Text = $"GetFileDetails Error";
            }
        }
        public void GetFile(string fileName)
        {
            FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite,Convert.ToInt32(fileDet.FILESIZE));
            byte[] receiveBytes = new byte[256];
            int bytes = 0;
            try
            {
                int i = 0;
                while (fs.Length!= Convert.ToInt64(fileDet.FILESIZE))
                {   
                    altoButton1.Enabled = false;
                    altoButton3.Enabled = false;
                    bytes = stream.Read(receiveBytes, 0, receiveBytes.Length);
                    fs.Write(receiveBytes, 0, bytes);
                    altoTextBox1.Text = $"{i} part of file received {fs.Length}";
                    i++;
                }
                fs.Close();
                altoButton1.Enabled = true;
                altoButton3.Enabled = true;
            }
            catch (Exception eR)
            {
                altoTextBox1.Text = eR.Message;
            }
        }
        public void SendFileInfo(FileStream fs)
        {
            try
            {
                fileDet.FILETYPE = Path.GetExtension(fs.Name);
                fileDet.FILESIZE = Convert.ToString(fs.Length);
                string json = JsonConvert.SerializeObject(fileDet);
                byte[] bytes = Encoding.UTF8.GetBytes(json);
                stream.Write(bytes, 0, bytes.Length);
            }
            catch (Exception ex)
            {
            }
        }
        private void SendFile(FileStream fs)
        {
            byte[] bytes = new byte[256];
            int size = 0;
            try
            {
                while ((size = fs.Read(bytes, 0, bytes.Length)) > 0)
                {
                    stream.Write(bytes, 0, size);
                }
                fs.Close();
            }
            catch
            {
                altoTextBox1.Text = "Sending file error";
            }
        }
Спасибо за любую помощь!
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
14.08.2020, 13:33
Ответы с готовыми решениями:

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

Добавление лишних символов в начало файла при его передаче по tcp
Есть tcp сервер и клиент передаю между ними файл файл приходит с дописанными в начале несколькими символами. Из-за чего он дописывает...

XModem и потеря пакета при передаче
Доброго всем дня. Есть 2 программы (сервер на Дельфи, клиент на Турбо-Паскале в промышленном контроллере), обменивающиеся файлами по...

8
Пора на C++?
 Аватар для TrickyBestia
370 / 264 / 99
Регистрация: 10.04.2020
Сообщений: 1,275
14.08.2020, 13:36
Цитата Сообщение от VladimirKovyako Посмотреть сообщение
сервер разбивает файл на 1450 частей
Зачем?
0
-1 / 0 / 0
Регистрация: 20.06.2016
Сообщений: 12
14.08.2020, 13:38  [ТС]
Я читал разные форумы, где было показано разбиение файла на части, собственно здесь также использовал данный подход, но мне кажется дело не в этом т.к 50\50 работает всё нормально, т.е файл приходит полностью
0
Эксперт .NET
6691 / 4102 / 1607
Регистрация: 09.05.2015
Сообщений: 9,574
14.08.2020, 14:03
Если уж вы используете NetworkStream, тогда используйте вместе с ним BinaryReader/BinaryWriter и не будет таких проблем...
Сразу вся эта ваша сериализация в json, циклы с stream.DataAvailable и прочий мусор станут ненужными...
0
-1 / 0 / 0
Регистрация: 20.06.2016
Сообщений: 12
14.08.2020, 14:16  [ТС]
Я вас понял, но до сих пор не понимаю почему теряются части файла, ибо я провёл много тестов и раз на раз не приходится один раз работает без нареканий, второй клиент получает не все части с сервера

Добавлено через 2 минуты
Цитата Сообщение от Someone007 Посмотреть сообщение
Если уж вы используете NetworkStream, тогда используйте вместе с ним BinaryReader/BinaryWriter и не будет таких проблем...
Сразу вся эта ваша сериализация в json, циклы с stream.DataAvailable и прочий мусор станут ненужными...
stream.DataAvailable у меня только в получении метаданных, тут с этим проблем нет , было проверено. Проблема именно с получением файла
0
Эксперт .NET
6691 / 4102 / 1607
Регистрация: 09.05.2015
Сообщений: 9,574
14.08.2020, 14:30
С этим у вас как раз проблемы... На клиенте часть данных тупо теряется, т.к. протокол обмена реализован крайне криво, и нигде не проверяется сколько байт отправлено и сколько нужно принять.
0
-1 / 0 / 0
Регистрация: 20.06.2016
Сообщений: 12
14.08.2020, 14:36  [ТС]
Цитата Сообщение от Someone007 Посмотреть сообщение
С этим у вас как раз проблемы... На клиенте часть данных тупо теряется, т.к. протокол обмена реализован крайне криво, и нигде не проверяется сколько байт отправлено и сколько нужно принять.
Возможно я чего-то не понимаю, но почему не проверяется, сначала приходит объект FileDetails где хранится информация какой тип файла и какой размер сейчас придет (GetFileDetails) и далее происходит получение файла до тех пор пока не получим столько сколько было сказано в метаданных, проверяет это строка в GetFile
C#
1
while (fs.Length!= Convert.ToInt64(fileDet.FILESIZE))
0
Эксперт .NET
6691 / 4102 / 1607
Регистрация: 09.05.2015
Сообщений: 9,574
14.08.2020, 14:51
Лучший ответ Сообщение было отмечено VladimirKovyako как решение

Решение

Вот тут вы можете принять больше байт чем было отправлено...
C#
1
2
3
4
5
6
7
8
9
10
11
                byte[] data = new byte[256];
                StringBuilder sb = new StringBuilder();
                int bytes = 0;
                do
                {
                    bytes = stream.Read(data, 0, data.Length);
                    sb.Append(Encoding.UTF8.GetString(data));
                }
                while (stream.DataAvailable);             
                gettedMessage = sb.ToString();
                string output = new string(gettedMessage.Where(c => char.IsLetter(c) || char.IsDigit(c) || char.IsSymbol(c) || char.IsSeparator(c) || char.IsPunctuation(c)).ToArray());
Добавлено через 12 минут
Код клиента при использовании BInaryReader/Writer можно было бы упростить
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
        TcpClient client;
        NetworkStream stream;
        BinaryReader reader;
        BinaryWriter writer;
        string ip;
        int port;
 
        public Form1()
        {
            InitializeComponent();
 
            client = new TcpClient();
            client.Connect(ip, port);
            Thread t = new Thread(new ThreadStart(ReceiveMessage));
            t.Start();
            stream = client.GetStream();
            reader = new BinaryReader(stream);
            writer = new BinaryWriter(stream);
        }
 
        public void ReceiveMessage()
        {
            while (true)
            {
                string messageType = reader.ReadString();
 
                if (messageType == "image")
                {
                    string fileName = reader.ReadString();
                    int fileSize = reader.ReadInt32(); // 2 GB max
                    byte[] imageData = reader.ReadBytes(fileSize);
 
                    using (FileStream fs = new FileStream(fileName, FileMode.Create))
                    {
                        fs.Write(imageData, 0, imageData.Length);
                    }
                }
            }
        }
 
        public void SendFile(string fileName)
        {
            FileInfo fileInfo = new FileInfo(fileName);
 
            if (fileInfo.Length > int.MaxValue)
                throw new Exception("file too big");
 
            using (FileStream fs = fileInfo.OpenRead())
            {
                writer.Write("image"); // messageType
                writer.Write(Path.GetFileName(fileName)); // fileName
                writer.Write((int)fs.Length); // fileSize
                fs.CopyTo(writer.BaseStream); // imageData
            }
        }
1
-1 / 0 / 0
Регистрация: 20.06.2016
Сообщений: 12
14.08.2020, 18:11  [ТС]
Цитата Сообщение от Someone007 Посмотреть сообщение
Вот тут вы можете принять больше байт чем было отправлено...
C#
1
2
3
4
5
6
7
8
9
10
11
                byte[] data = new byte[256];
                StringBuilder sb = new StringBuilder();
                int bytes = 0;
                do
                {
                    bytes = stream.Read(data, 0, data.Length);
                    sb.Append(Encoding.UTF8.GetString(data));
                }
                while (stream.DataAvailable);             
                gettedMessage = sb.ToString();
                string output = new string(gettedMessage.Where(c => char.IsLetter(c) || char.IsDigit(c) || char.IsSymbol(c) || char.IsSeparator(c) || char.IsPunctuation(c)).ToArray());
Добавлено через 12 минут
Код клиента при использовании BInaryReader/Writer можно было бы упростить
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
        TcpClient client;
        NetworkStream stream;
        BinaryReader reader;
        BinaryWriter writer;
        string ip;
        int port;
 
        public Form1()
        {
            InitializeComponent();
 
            client = new TcpClient();
            client.Connect(ip, port);
            Thread t = new Thread(new ThreadStart(ReceiveMessage));
            t.Start();
            stream = client.GetStream();
            reader = new BinaryReader(stream);
            writer = new BinaryWriter(stream);
        }
 
        public void ReceiveMessage()
        {
            while (true)
            {
                string messageType = reader.ReadString();
 
                if (messageType == "image")
                {
                    string fileName = reader.ReadString();
                    int fileSize = reader.ReadInt32(); // 2 GB max
                    byte[] imageData = reader.ReadBytes(fileSize);
 
                    using (FileStream fs = new FileStream(fileName, FileMode.Create))
                    {
                        fs.Write(imageData, 0, imageData.Length);
                    }
                }
            }
        }
 
        public void SendFile(string fileName)
        {
            FileInfo fileInfo = new FileInfo(fileName);
 
            if (fileInfo.Length > int.MaxValue)
                throw new Exception("file too big");
 
            using (FileStream fs = fileInfo.OpenRead())
            {
                writer.Write("image"); // messageType
                writer.Write(Path.GetFileName(fileName)); // fileName
                writer.Write((int)fs.Length); // fileSize
                fs.CopyTo(writer.BaseStream); // imageData
            }
        }
Спасибо тебе огромное, друг. Посидел часик переписал, поняв твою идеологию, и больше такой проблемы не появлялось при 30-40 тестах. Просто спасибо, что существуют такие люди, как ты, надеюсь когда-нибудь и я смогу кому-то помочь. Спасибо!
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
14.08.2020, 18:11
Помогаю со студенческими работами здесь

Потеря пакетов при передаче клиент->сервер - Boost C++
Написал простенькую реализацию сервера и клиента. Клиент: #include &quot;stdafx.h&quot; #include &lt;boost/asio.hpp&gt; #include...

SPI в AVR. Потеря первого байта при передаче строки
Доброго времени суток господа. При попытке передать 16 символьную строку, от master к slave, 1 символ (2 байта) постоянно теряется, причем...

Максимальный обьем при передаче по tcp
максимальный обьем при передаче по udp протоколу 65 килобайт а по tcp сколько?

Варьирование таймаута при передаче по TCP/IP
Доброго дня! В общем есть задание, реализовать клиент серверное приложение, которое будет: 1. Передавать 32 кб информации,...

Ошибка при передаче изображения по TCP
Ошибка при передаче изображения по TCP? Клиент: Bitmap printscreen = new Bitmap(Screen.PrimaryScreen.Bounds.Width,...


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

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
SDL3 для Web (WebAssembly): Установка Emscripten SDK (emsdk) и CMake для сборки C и C++ приложений в Wasm
8Observer8 30.01.2026
Содержание блога Для того чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: Install for Windows. Следуйте стандартной процедуре установки Git через установщик. . . .
SDL3 для Android: Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования. Часть библиотеки BedvitCOM Использованы. . .
SDL3 для Android: Загрузка PNG с альфа-каналом с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru