Модераторы: LSD, AntonSaburov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Теряется соединение 
V
    Опции темы
enzaime
Дата 15.3.2014, 10:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 28
Регистрация: 16.8.2013

Репутация: нет
Всего: нет



Всем привет, решил создать простенькое взаимодействие клиент/сервер и столкнулся с проблемой потери связи, в чём проблема не пойму(ошибка connection reset) Вот код:
Сервер
Код

public class Server2 {

    public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub
        ServerSocket srvr=new ServerSocket(8189);
        Socket s;
        System.out.println("сервер работает");
        int i=0;
        while(true)
        {
            s=srvr.accept();
            i++;
            System.out.println("соединение "+i);
            Thread t=new Thread(new MClient(s));
        }

    }

}

Код

public class MClient implements Runnable
{
    InputStream is;
    OutputStream os;
    BufferedReader br;
    Socket s;
    public MClient(Socket s)
    {
        this.s=s;
    }

    @Override
    public void run() {
        
        try {
            is = s.getInputStream();
            os = s.getOutputStream();      
            br = new BufferedReader(new InputStreamReader(is));    
            System.out.println(br.readLine()+" от клиента");
            String mes="слово";
            byte []b=mes.getBytes();
            os.write(b);
            s.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            System.out.println("чё-то не вышло");
            e.printStackTrace();
        }
        
    }

}

Клиент
Код


public class Klient {
    public static void main(String[] args) throws UnknownHostException, IOException {
        // TODO Auto-generated method stub
        Socket s;    
        s=new Socket("127.0.0.1", 8189);
        ThreadKlient tk=new ThreadKlient(s);
        Thread t=new Thread(tk);
        t.start();

    }

}

Код

public class ThreadKlient implements Runnable
{
    InputStream is;
    OutputStream os;
    BufferedReader br;
    Socket s;
    public ThreadKlient(Socket s)
    {
        this.s=s;
    }
    @Override
    public void run() {
            try {
                is = s.getInputStream();
                os = s.getOutputStream();  
                br = new BufferedReader(new InputStreamReader(is));    
                System.out.println(br.readLine()+"от сервера");
                String mes="ответ";
                byte []b=mes.getBytes();
                os.write(b);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }        
      }
}


PM MAIL   Вверх
Pawl
Дата 15.3.2014, 11:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 649
Регистрация: 22.4.2008
Где: Витебск

Репутация: 1
Всего: 28



вот сдесь
Код

Thread t=new Thread(new MClient(s));

надо бы добавить 
Код

Thread t=new Thread(new MClient(s));
t.start();



--------------------
В действительности всё совсем не так, как на самом деле
PM MAIL   Вверх
enzaime
Дата 15.3.2014, 15:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 28
Регистрация: 16.8.2013

Репутация: нет
Всего: нет



да точно забыл я про это, но всё равно проблема остается.
PM MAIL   Вверх
Pawl
Дата 15.3.2014, 20:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 649
Регистрация: 22.4.2008
Где: Витебск

Репутация: 1
Всего: 28



не делайте запрос от клиента многопоточным - нет смысла, т. к. клиент все-равно шлет запросы по очереди, а не одновременно. Вот рабочий вариант клиента:
Код

package client;

import java.io.IOException;
import java.net.Socket;

public class Client {
    public static void main(String[] args) {
        try {
            Socket s = new Socket("127.0.0.1", 8189);
            new ThreadKlient(s).start();
        } catch (IOException ex) {
            System.out.print(ex.getMessage());
        }
    }
}
Код

package client;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

public class ThreadKlient {
    Socket s;
    BufferedReader br;
    PrintWriter out;

    public ThreadKlient(Socket s) {
        this.s = s;
    }

    public void start() throws IOException {
        try {
            br = new BufferedReader(new InputStreamReader(s.getInputStream()));
            out = new PrintWriter(s.getOutputStream(), true);
            String mes = "ответ";
            out.println(mes);
            System.out.println(br.readLine() + " от сервера");
        } finally {
            if (br != null) {
                br.close();
            }
            
            if (out != null) {
                out.close();
            }
            if (s != null) {
                s.close();
            }            
        }
    }
}

Если все-же делать многопоточным, надо в каждом потоке создавать свой сокет.

Это сообщение отредактировал(а) Pawl - 15.3.2014, 21:36


--------------------
В действительности всё совсем не так, как на самом деле
PM MAIL   Вверх
enzaime
Дата 15.3.2014, 21:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 28
Регистрация: 16.8.2013

Репутация: нет
Всего: нет



Pawl у меня к вам такой вот вопрос, насчёт s.close(), получается, что будет отослано 1 сообщение и соединение закроется. Вопрос такой: при посылке следующего сообщения от того же клиента надо заново соединяться к серверу? И можно ли как-то не разрывать это соединение, а держать постоянно, для постоянного обмена сообщениями?

PM MAIL   Вверх
Pawl
Дата 15.3.2014, 22:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 649
Регистрация: 22.4.2008
Где: Витебск

Репутация: 1
Всего: 28



Цитата(enzaime @  15.3.2014,  21:56 Найти цитируемый пост)
И можно ли как-то не разрывать это соединение, а держать постоянно, для постоянного обмена сообщениями?

Можно организовать бесконечный цикл, как в этом или этом примерах.


--------------------
В действительности всё совсем не так, как на самом деле
PM MAIL   Вверх
enzaime
Дата 15.3.2014, 22:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 28
Регистрация: 16.8.2013

Репутация: нет
Всего: нет



Я вот тут написал, но как-то не понимаю в чём причина (проблема в классе ThreadKlient)
Код

public class Klient {
    public static void main(String[] args) {
        try {
            Socket s = new Socket("127.0.0.1", 8189);
            new ThreadKlient(s).start();
        } catch (IOException ex) {
            System.out.print(ex.getMessage());
        }
    }
}

Код

public class ThreadKlient {
    Socket s;
    public ThreadKlient(Socket s) {
        this.s = s;
    }
    public void start() throws IOException {
       
        String mes = "ответ";
        BufferedReader br = new BufferedReader(
                new InputStreamReader(s.getInputStream()));
        PrintWriter out = new PrintWriter(s.getOutputStream(), true);
        int i=0;
        
        while(i!=2)
        {
            out.println(mes);
            System.out.println(br.readLine());    
            out.flush();
            i++;
        } 
        br.close();
        out.close();
        s.close();
    }
}

первый раз нормально от сервера приходит ответ, второй раз null, а на сервере 1 раз приходит ответ от клиента
сервер
Код

public class Server {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        try{
            int i=0;
            ServerSocket s=new ServerSocket(8189);
            System.out.println("Server is started");
            while(true)
            {    
                User u=new User(i,s.accept());
                u.start();
                i++;
                System.out.println(i);
            }
        }
        catch(IOException e)
        {
            System.out.println("init error: "+e);
        }
        

    }
}

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

public class User extends Thread{
    Socket s;
    int num;
     InputStream is;
     OutputStream os;    
     BufferedReader br;
     int count=0;
    public User(int i,Socket s)
    {
        num=i;
        this.s=s;
        
    }
    public void run() {
        // TODO Auto-generated method stub
        try
        {
            try{
                is = s.getInputStream();
                os = s.getOutputStream();      
                br = new BufferedReader(new InputStreamReader(is));
                System.out.println(br.readLine()+" от клиента");
                String mes="проверка от сервера";
                byte b[]=mes.getBytes();
                os.write(b);
                os.flush();
            }
            finally{
                System.out.println("закрыт");
                s.close();
            }
        }
        catch(IOException e)
        {
         System.out.println("init error: "+e);
         System.out.println("поток из server user");
        } 
        
        
        
    }
}

PM MAIL   Вверх
Pawl
Дата 15.3.2014, 23:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 649
Регистрация: 22.4.2008
Где: Витебск

Репутация: 1
Всего: 28



Цитата(enzaime @  15.3.2014,  22:18 Найти цитируемый пост)
первый раз нормально от сервера приходит ответ, второй раз null, а на сервере 1 раз приходит ответ от клиентасервер

Попробуйте каждый раз отправлять запрос с нового сокета:
Код

import java.io.IOException;

public class Client {
    public static void main(String[] args) {
        try {
            new ThreadKlient().start();
        } catch (IOException ex) {
            System.out.print(ex.getMessage());
        }
    }
}
Код

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

public class ThreadKlient {
    Socket s;
    BufferedReader br;
    PrintWriter out;

    public void start() throws IOException {
        String mes = "ответ";
        int i = 0;
        while (i <= 2) {
            s = new Socket("127.0.0.1", 8189);
            br = new BufferedReader(
                    new InputStreamReader(s.getInputStream()));
            out = new PrintWriter(s.getOutputStream(), true);            
            out.println(mes);
            System.out.println(br.readLine());
            out.flush();
            br.close();
            out.close();
            s.close();            
            i++;
        }
    }
}



--------------------
В действительности всё совсем не так, как на самом деле
PM MAIL   Вверх
enzaime
Дата 16.3.2014, 10:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 28
Регистрация: 16.8.2013

Репутация: нет
Всего: нет



Я тоже об этом думал, но тогда как-то неправильно выходит. Например, у Хорстмана есть пример в котором описан консольный сервер, который отсылает назад все сообщения от клиента (клиент: привет. сервер: ECHO привет). Там роль клиента исполняет программа telnet (входит в пакет windows). Там держится постоянное соединение, а если использовать каждый раз новый сокет, то получается, что 1 пользователь регистрируется на сервере n-ое количество раз. Т.е. это всё равно что после каждого сообщения на форуме проходить авторизацию ( ну это я так это вижу, но всё-таки мне кажется, что для каждого клиента нужно использовать 1 пару сокетов (1 сокет у клиента, 2 у сервера)).
PM MAIL   Вверх
Pawl
Дата 16.3.2014, 11:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 649
Регистрация: 22.4.2008
Где: Витебск

Репутация: 1
Всего: 28



Цитата(enzaime @  16.3.2014,  10:59 Найти цитируемый пост)
Т.е. это всё равно что после каждого сообщения на форуме проходить авторизацию

На самом деле, когда приходит запрос от клиента к серверу, тот всегда воспринимает его, как новый. Сервер ничего не знает о предыдущих запросах. Принцип работы тут такой: сервер "слушает" какой-то порт, запрос от клиента инициирует открытие соединения. Сервер отвечает, после чего инициирует закрытие, и "забывает" об этом. Т. е. от клиента закрытие соединения не зависит. Хочешь соединиться снова - открывай новое соединение. Что же до авторизаций на форуме и пр., тут есть еще понятие сессии, это уже несколько из другой оперы, и скорее относится к web-программированию.

Это сообщение отредактировал(а) Pawl - 16.3.2014, 11:27


--------------------
В действительности всё совсем не так, как на самом деле
PM MAIL   Вверх
enzaime
Дата 16.3.2014, 16:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 28
Регистрация: 16.8.2013

Репутация: нет
Всего: нет



Я таки разобрался в чём причина была. Соединение терялось так как была ошибка записывания/считывания потока BufferedReader/PrintWriter, из-за этого сокет на стороне клиента разрывал соединение (скорее всего ошибка была связана с освобождением ресурсов потоков или как-то так (если например записать/считать потоки а потом применить метод сокета close(), то всё норм, следовательно в close() правильно обращается с потоками в отличие от меня)).Вот рабочий вариант, если кому интересно.
Сервер
Код


public class Server {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        try{
            int i=0;
            ServerSocket s=new ServerSocket(8189);
            System.out.println("Server is started");
            while(true)
            {    
                User u=new User(i,s.accept());
                u.start();
                i++;
                System.out.println(i);
            }
        }
        catch(IOException e)
        {
            System.out.println("init error: "+e);
        }
        

    }
}

Код

public class User extends Thread{
    Socket s;
    int num;
     InputStream is;
     OutputStream os;    
     BufferedReader br;
     PrintWriter out;
     int count=0;
    public User(int i,Socket s)
    {
        num=i;
        this.s=s;
        
        
    }
       public void run() {
           try {
               BufferedReader in = new BufferedReader(
                       new InputStreamReader(s.getInputStream()));
                out = new PrintWriter(s.getOutputStream(), true);

               out.println("Hello, you are client #" + num + ".");
               out.println("Enter a line with only a period to quit\n");
               while (true) {
                   String input = in.readLine();
                   Server.history=Server.history+"\n"+input;
                   if (input == null || input.equals(".")) {
                       break;
                   }  
                   out.println(input.toUpperCase());
               }
           } catch (IOException e) {
               log("Error handling client# " + num + ": " + e);
           } finally {
               try {
                   s.close();
               } catch (IOException e) {
                   log("Couldn't close a socket, what's going on?");
               }
               log("Connection with client# " + num + " closed");
           }
       }

     
       private void log(String message) {
           System.out.println(message);
       }
}

Клиент (написанный с использованием Swing и SWT(SWT для Eclipse(нужно подключить библиотеку org.eclipse.swt))
Код

public class Klient {
    public static void main(String[] args) {
            new SwingView();
            //new SWTView();
    }
}

Код

public class SwingView {
    JButton send;
    JButton connect;
    JTextArea server;
    JTextField message;
    JFrame frame;
    JTextArea history;
    private BufferedReader in;
    private PrintWriter out;
    public SwingView()
    {
        frame=new JFrame("клиент");
        send=new JButton("отправить");
        connect=new JButton("соединение");
        server=new JTextArea("127.0.0.1/8189");
        message=new JTextField("сообщение");
        history=new JTextArea();
        frame.setSize(400,400);
        JPanel panel=new JPanel();
        panel.setLayout(new GridLayout(2, 2));
        panel.add(server);
        panel.add(connect);
        panel.add(message);
        panel.add(send);
        Box box=new Box(BoxLayout.Y_AXIS);
        box.add(panel);
        box.add(history);
        frame.add(box,BorderLayout.NORTH);
        
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        connect.addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                super.mousePressed(e);
                start();
            }
        });
        send.addActionListener(new ActionListener() {
            
            @Override
            public void actionPerformed(ActionEvent e) {
                send();
            }
        });
    }
    public void start() {
        try {
            Socket s = new Socket(getHost(), getPort());
            in = new BufferedReader(
                    new InputStreamReader(s.getInputStream()));
            out = new PrintWriter(s.getOutputStream(), true);
            for (int i = 0; i < 3; i++) {
                System.out.println(in.readLine() + "\n");
            }
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }  
    }
    public void send()
    {
        out.println(message.getText());
        String response;
     try {
         response = in.readLine();
         if (response == null || response.equals("")) {
               System.exit(0);
           }
     } catch (IOException ex) {
            response = "Error: " + ex;
     }
     history.setText(response);
     message.selectAll();
    }
    public int getPort()
    {
        String p=server.getText();
        int port=Integer.parseInt(p.substring(p.indexOf("/")+1, p.length()));
        return port;
    }
    public String getHost()
    {
        String p=server.getText();
        return p.substring(0,p.indexOf("/"));
    }

}

Код

public class SWTView {
    private BufferedReader in;
    private PrintWriter out;
    Button send;
    Button connect;
    Text serverName;
    Text message;
    Text history;
    Thread t;
    boolean flag=false;
    public SWTView() {
        Display display = new Display(); 
        Shell shell = new Shell(display);
        shell.setText("SWT Hello");
        shell.setSize(400, 400);
        Group border = new Group(shell, SWT.SHADOW_OUT);
        FillLayout fillLayout=new FillLayout(SWT.VERTICAL);
        shell.setLayout(fillLayout);
        GridLayout gridLayout = new GridLayout(2, true);
        border.setLayout(gridLayout);
        serverName = new Text(border, SWT.LEFT);
        connect = new Button(border, SWT.RIGHT);
        connect.setText("Подключиться");
        message = new Text(border, SWT.LEFT);
        send = new Button(border, SWT.RIGHT);
        send.setText("Отправить");
        history = new Text(shell, SWT.MULTI | SWT.BORDER | SWT.V_SCROLL);
        message.setLayoutData(new GridData(SWT.FILL, 60, true, true));
        serverName.setLayoutData(new GridData(SWT.FILL, 60, true, true));
        connect.setLayoutData(new GridData(SWT.FILL, 60, true, true));
        send.setLayoutData(new GridData(SWT.FILL, 60, true, true)); 
        serverName.setText("127.0.0.1/8189");
        message.setText("ksfksdhfgkdfgdfljk"); 
        send.addMouseListener(new MouseAdapter() {
            
            @Override
            public void mouseUp(MouseEvent e) {
                send();
            }
            
        });
        
        connect.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseUp(MouseEvent e) {
                    start();
            }
        });
        
        shell.open();
        while (!shell.isDisposed()) {
        if (!display.readAndDispatch()) {
                display.sleep();
            }
        }
        display.dispose();   
    }
    public void start() {
        try {
            Socket s = new Socket(getHost(), getPort());
            in = new BufferedReader(
                    new InputStreamReader(s.getInputStream()));
            out = new PrintWriter(s.getOutputStream(), true);
            for (int i = 0; i < 3; i++) {
                System.out.println(in.readLine() + "\n");
            }
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }  
    }
    public void send()
    {
        out.println(message.getText());
        String response;
     try {
         response = in.readLine();
         if (response == null || response.equals("")) {
               System.exit(0);
           }
     } catch (IOException ex) {
            response = "Error: " + ex;
     }
     history.setText(response);
     message.selectAll();
    }
    
    public int getPort()
    {
        String p=serverName.getText();
        int port=Integer.parseInt(p.substring(p.indexOf("/")+1, p.length()));
        return port;
    }
    public String getHost()
    {
        String p=serverName.getText();
        return p.substring(0,p.indexOf("/"));
    }

}

Осталось добавить историю сообщений.
Спасибо всем, кто пытался помочь.
PM MAIL   Вверх
Pawl
Дата 16.3.2014, 19:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 649
Регистрация: 22.4.2008
Где: Витебск

Репутация: 1
Всего: 28



В этом случае также для каждого соединения в клиенте создается новый сокет - всякий раз, когда нажимается кнопка "соединение" и вызывается метод start(), происходит создание нового сокета:
Код

 public void start() {
        ...
            Socket s = new Socket(getHost(), getPort());
        ...


Это сообщение отредактировал(а) Pawl - 16.3.2014, 19:23


--------------------
В действительности всё совсем не так, как на самом деле
PM MAIL   Вверх
enzaime
Дата 16.3.2014, 19:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 28
Регистрация: 16.8.2013

Репутация: нет
Всего: нет



В проге надо нажать 1 раз соединение и больше не надо (просто я не стал её блокировать). А так если нажать на соединение, потом отослать сообщение больше 1 раза, то оно (соединение) не разрывается, а держится постоянно.
PM MAIL   Вверх
Pawl
Дата 16.3.2014, 19:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 649
Регистрация: 22.4.2008
Где: Витебск

Репутация: 1
Всего: 28



Я думал, вам надо организовать диалог клиент-сервер (типа вопрос-ответ), а не простую отправку сообщений серверу.


--------------------
В действительности всё совсем не так, как на самом деле
PM MAIL   Вверх
enzaime
Дата 16.3.2014, 19:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 28
Регистрация: 16.8.2013

Репутация: нет
Всего: нет



В любом случае спасибо за помощь, я в итоге получил что хотел.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: Работа с сетью | Следующая тема »


 




[ Время генерации скрипта: 0.1699 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.