forum.boolean.name

forum.boolean.name (http://forum.boolean.name/index.php)
-   С# (http://forum.boolean.name/forumdisplay.php?f=128)
-   -   Сетевое программирование (http://forum.boolean.name/showthread.php?t=18674)

Okay 02.11.2013 23:57

Сетевое программирование
 
Нашел в интернете пример Клиент-Сервера.
Все работает, понял как работает подключение к серверу, но не знаю как делать проверку на подключение =)

Код сервера
static void Main(string[] args)
{
TcpListener listner = new TcpListener(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 12000));
listner.Start();
while (true)
{
TcpClient client = listner.AcceptTcpClient();

StreamReader sr = new StreamReader(client.GetStream());
Console.WriteLine("Client : " + sr.ReadLine());

StreamWriter sw = new StreamWriter(client.GetStream());
sw.AutoFlush = true;
Console.WriteLine("Server : Привет");
sw.WriteLine("Привет");

Console.WriteLine("Client : " + sr.ReadLine());
Console.WriteLine("Server : Пока");
sw.WriteLine("Пока");

client.Close();
}
}

pax 03.11.2013 00:24

Ответ: Сетевое программирование
 
Отличная статья по клиент-серверу на C#: http://msdn.microsoft.com/ru-ru/library/dd335942.aspx

Okay 04.11.2013 00:26

Ответ: Сетевое программирование
 
Цитата:

Сообщение от pax (Сообщение 269602)
Отличная статья по клиент-серверу на C#: http://msdn.microsoft.com/ru-ru/library/dd335942.aspx

Ну как бы статья не фонтан, я хочу сказать.
Статья для профессионалов, я к ним не отношусь, к сожалению...

Andvrok 04.11.2013 00:48

Ответ: Сетевое программирование
 
Цитата:

Сообщение от Okay (Сообщение 269625)
Ну как бы статья не фонтан, я хочу сказать.
Статья для профессионалов, я к ним не отношусь, к сожалению...

Ну хрен знает, на мой взгляд статья максимально простая, сомневаюсь что у тебя получится найти что-нибудь проще, разве что только в учебнике по программированию каком-то.

Okay 04.11.2013 01:41

Ответ: Сетевое программирование
 
Цитата:

Сообщение от Andvrok (Сообщение 269627)
Ну хрен знает, на мой взгляд статья максимально простая, сомневаюсь что у тебя получится найти что-нибудь проще, разве что только в учебнике по программированию каком-то.

Нашел =) На том же сайте, только не понимаю зачем при отправке сообщения серверу, требуется засылать строковую переменную в массив. Может быть кто знает?

string Message = Console.ReadLine();
Byte[] data = System.Text.Encoding.ASCII.GetBytes(Message);
NetworkStream stream = client.GetStream();
stream.Write(data, 0, data.Length);

pax 04.11.2013 09:55

Ответ: Сетевое программирование
 
Сервер передает байты, строка не байты а символы. Чтобы получить байты из строки, надо преобразовать строку какой-то кодировкой в байты. В твоем примере эта кодировка ASCII.

Okay 04.11.2013 18:27

Ответ: Сетевое программирование
 
Почему ошибка?



Класс клиента в юнити
Код:

public class Test : MonoBehaviour {
        Client client;
        // Use this for initialization
        void Start ()
        {
        string connect = "Connected";
                client = new Client("127.0.0.1", 12000);
        SendMessage(connect);
        }
       
        // Update is called once per frame
        void Update () {
       
        }
}

Класс клиента в C#
Код:

class Client
{
    TcpClient client;
    public Client(string IpAdress, int port)
    {
        client = new TcpClient(IpAdress, port);
    }
    public void SendMessage(string Message)
    {
        Message.Trim();
        Byte[] data = System.Text.Encoding.ASCII.GetBytes(Message);
        NetworkStream stream = client.GetStream();
        stream.Write(data, 0, data.Length);

    }
       
}

Класс сервера
Код:

class Program
    {
        static void Main(string[] args)
        {
            TcpListener listner = new TcpListener(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 12000));
            listner.Start();
            Byte[] bytes = new Byte[256];
            String data = null;
            while (true)
            {
                TcpClient client = listner.AcceptTcpClient();
                Console.WriteLine("Подключился клиент");

                data = null;

                NetworkStream stream = client.GetStream();
                stream.Read(bytes, 0, bytes.Length);
                data = System.Text.Encoding.ASCII.GetString(bytes, 0, data.Length);
                Console.WriteLine("Received: {0}", data);
           
                client.Close();
            }
        }
    }


pax 04.11.2013 20:20

Ответ: Сетевое программирование
 
а где функция Connected, которой предназначен мессадж? или ты просто забыл перед SendMessage написать client: client.SendMessage(connect )

Okay 04.11.2013 20:40

Ответ: Сетевое программирование
 
Цитата:

Сообщение от pax (Сообщение 269658)
а где функция Connected, которой предназначен мессадж? или ты просто забыл перед SendMessage написать client: client.SendMessage(connect )

Ооу, спасибо большое. Я что-то не досмотрел, что SendMessage используется как метод
Как бы отчет

Okay 05.01.2014 12:21

Ответ: Сетевое программирование
 
Значит есть код
Код:

static void Main(string[] args)
        {
            TcpListener listner = new TcpListener(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 12000));
            listner.Start();
            Byte[] bytes = new Byte[256];
            String data = null;
            while (true)
            {
                TcpClient client = listner.AcceptTcpClient();
                Console.WriteLine("Подключился клиент");

                data = null;

                NetworkStream stream = client.GetStream();
                stream.Read(bytes, 0, bytes.Length);
                data = System.Text.Encoding.ASCII.GetString(bytes, 0, bytes.Length);
                Console.WriteLine("Received: {0}", data);
               
           
                client.Close();
            }
        }
        public void SendMessage(string Message)
        {
            Message.Trim();
            Byte[] data = System.Text.Encoding.ASCII.GetBytes(Message);
            NetworkStream stream = client.GetStream();
            stream.Write(data, 0, data.Length);

        }

Как сделать, чтобы отправлялось сообщение клиенту, который прислал сообщение на сервер?

pax 05.01.2014 13:13

Ответ: Сетевое программирование
 
вероятно надо выполнить отправку перед строкой
PHP код:

client.Close(); 


Okay 05.01.2014 14:26

Ответ: Сетевое программирование
 
Цитата:

Сообщение от pax (Сообщение 272187)
вероятно надо выполнить отправку перед строкой
PHP код:

client.Close(); 


Как все сложно. Лучше UDP тогда использовать

moka 05.01.2014 15:36

Ответ: Сетевое программирование
 
Ты ещё не начал сетевого программирования, а уже "сложно"..

DStalk 27.11.2015 01:18

Ответ: Сетевое программирование
 
Товарищи, подскажите: имеется простенький клиент. В цикле вызывается readSocket(), для проверки доступных данных для чтения используется NetworkStream.DataAvailable. Читать данные удобнее именно строками, но для этих целей явно не подходит DataAvailable - иногда данные "висят" до следующей строки (одна строчка прочиталась из потока, DataAvailable сбросилось, следующая строка не читается пока новая не придет).
Гуглил, но решения именно с ReadLine() не нашел, может кто подскажет как по другому сделать проверку на пришедшие данные?

PHP код:

tcp_socket = new TcpClient(hostport);
            
net_stream tcp_socket.GetStream();
socket_writer = new StreamWriter(net_stream);
socket_reader = new StreamReader(net_stream);

static public 
Boolean readSocket()
{
    if (
net_stream.DataAvailable) {
        
tcp_packet socket_reader.ReadLine();
        
//Тут обработка
        
return true;
    }
    return 
false;



Andvrok 27.11.2015 02:35

Ответ: Сетевое программирование
 
Цитата:

Сообщение от DStalk (Сообщение 301910)
Товарищи, подскажите: имеется простенький клиент. В цикле вызывается readSocket(), для проверки доступных данных для чтения используется NetworkStream.DataAvailable. Читать данные удобнее именно строками, но для этих целей явно не подходит DataAvailable - иногда данные "висят" до следующей строки (одна строчка прочиталась из потока, DataAvailable сбросилось, следующая строка не читается пока новая не придет).
Гуглил, но решения именно с ReadLine() не нашел, может кто подскажет как по другому сделать проверку на пришедшие данные?

PHP код:

tcp_socket = new TcpClient(hostport);
            
net_stream tcp_socket.GetStream();
socket_writer = new StreamWriter(net_stream);
socket_reader = new StreamReader(net_stream);

static public 
Boolean readSocket()
{
    if (
net_stream.DataAvailable) {
        
tcp_packet socket_reader.ReadLine();
        
//Тут обработка
        
return true;
    }
    return 
false;



Не совсем понял задачу. Я обычно пользуюсь не ридером, а BeginRead/BeginReadAsync стрима. В колбэке смотришь количество полученных байт - если больше нуля, то в стриме что-то есть.

Жека 27.11.2015 07:29

Ответ: Сетевое программирование
 
Можно твою функцию чтения сделать асинхронной - завернуть в обёртку, тогда получение не будет блокировать прогу.
Код:

static public async Task Boolean readSocket()
При этом нужно синхронизировать процесс обработки полученной строки c контекстом текущего потока (наверное).

DStalk 27.11.2015 09:21

Ответ: Сетевое программирование
 
Блокировка не важна. Вопрос чем заменить DataAvailable - например пришло сразу две строки, одну прочитали, DataAvailable сбросилось, вторая будет висеть и не прочитается пока не придет что-нибудь еще...
Что-то мне подсказывает, что от ReadLine() придется отказаться.:)

Жека 27.11.2015 12:00

Ответ: Сетевое программирование
 
Можно так: читать сокет в отдельном потоке в цикле. прочитанные строки отправлять в обработчик EventHandler.

Код:

public EventHandler<string> OnReadLine;

new Thread() {// псевдокод, не помню точный синтаксис

    while (net_stream.DataAvailable) {
        tcp_packet = socket_reader.ReadLine();
        if (OnReadLine != null)
            OnReadLine(this, new SocketEventArgs(tcp_packet));
    }

}.start();

public class SocketEventArgs : EventArgs {

    public string line;

    public SocketEventArgs(string s) {
        line = s;
    }
}

в итоге можно использовать полученные из сокета строки любым количеством слушателей.

Код:

socketWrapper.OnReadLine += (sender, args) => {
    // что-то делаем со строчками
}

socketWrapper - в принципе, можно и через статический доступ, у тебя же этот класс щас статический.

отправку данных можно тоже делать в отдельном потоке, выгребая все команды из списка-на-отправку.

pax 27.11.2015 14:34

Ответ: Сетевое программирование
 
Проблема вероятнее в том, что сервер не отправляет данные строки.
Попробуй установить на обоих сторонах вот этот флаг в True:
https://msdn.microsoft.com/ru-ru/lib...vs.110).asp x

h1dd3n 27.11.2015 20:14

Ответ: Сетевое программирование
 
Если как ты написал "блокировка не важна", то вся эта хрень с DataAvailable вообще не нужна.

Код:

var ns = tcpClient.GetStream();
var rdr = new StreamReader(ns);

var line = rdr.ReadLine();
while (line != null) {
    //обрабатываем строку...

    line = rdr.ReadLine();
}

rdr.ReadLine() будет блокировать выполнение пока либо не прочитает строку либо не наткнется на конец потока.

Если тебе нужно асинхронно принимать данные по сети и "делить на строки", то подход нужен совсем другой - 1 поток просто всегда читает данные из tcpClient и записывает в буффер, 2 поток (можно и в основном), читает данные из буффера и делит на строки, если там какой-то кусок "неполный", то его надо оставить в буффере до тех пор пока остальное не придет. На самом деле и чтение из потока и обработку данных можно тоже в одном потоке делать, просто так делать не принято (хоть и будет работать)

DStalk 28.11.2015 11:26

Ответ: Сетевое программирование
 
Всем спасибо.
В итоге сделал так, вроде работает без ошибок: :)

PHP код:

static byte[] bytes = new byte[8192];

tcp_socket = new TcpClient(hostport);
net_stream tcp_socket.GetStream();

static public 
Boolean readSocket() 

    while (
net_stream.DataAvailable) {
        
int len net_stream.Read(bytes0bytes.Length);
        
read_buffer += Encoding.UTF8.GetString(bytes,0,len);
    }

    if (
read_buffer.Length!=0)
    {
        
//Разделение на строки
        
int i read_buffer.IndexOf("\n");
        if (
> -1) {
            
tcp_values read_buffer.Substring(01));
            
read_buffer read_buffer.Substring(1);
            return 
true;
        }
    }
    return 
false;




Часовой пояс GMT +4, время: 20:45.

vBulletin® Version 3.6.5.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot