Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: Работа с сетью > socket.Close()


Автор: polakwilno 18.8.2008, 13:34
Добрый день,

Ситуация такая:

Создаю Н потоков (в одной ява програме), и каждый из них конектится к тому-же серверу. Проблема в том, что кодга один из них вызывает Close() метод, закрывается соединение и у других клиентов (у всех оставшихся Н-1 потоков).

1. Почему? (какойто общий идентификатор или что?)
2. Как с этим боротся? (т.е. есть-ли возможность работы нескольких клиентов из одной программы? просто хотел написать эмулятор клиентов и протестить сервер...)

Автор: neiron 18.8.2008, 14:26
У меня для тестирования сервака примерно такая же тулзень написана. Всё корректно работает. 
Ты бы хоть кусочек кода показал - где и что открывается, что в потоках делается, и как всё закрывается. 

Автор: polakwilno 18.8.2008, 14:53
Ясненько...

Вечерком вкину код

Спасибо ;)

Автор: polakwilno 10.9.2008, 20:48
Извиняюсь, был в отпуске )

Похоже я несовсем правильно описал ситуацию (или теперь по какимто причинам програма ведет себя по другому). Просто когда клиентов больше чем 3, иногда разрывается соединение раньше времени с некоторыми клиентами. 

Как все работает: после конекта к серверу клиент шлет строку "char(0x01)|ИМЯ". Сервер сохраняет ИМЯ и высылает клиенту строку "r", получив которую клиент закрывает свой сокет. Cервер, обнаружив разрыв соединения, выводит сообщение, что клиент с именем ИМЯ отсоеденился. Проблема в том, что если сделать, скажем 10 клиентов (лучше сразу 500 для 100% эфекта) то будет видно, что с некоторыми клиентами связь разрывается еще до того, как сервер сохранит имя этого клиента. Я уверен, что что-то не то с дисконектом, потомучто если ни одного клиента не закрывать, то ни одно из соединений не закрывается. Если-же все закрывать сразу после регистрации (после получения строки "r"), то некоторые соединения разрываются сами по себе (иначе сервер имел-бы имя этого клиента)

Вот сам код

Сервер

Main.java
Код

package testServer;

import java.io.IOException;
import java.net.ServerSocket;

public class Main {

    static ServerSocket serverSocket = null;
    /**
     * @param args
     */
    public static void main(String[] args) {
        try {
            serverSocket = new ServerSocket(6899);
            serverSocket.setSoTimeout(0);
            System.out.println(serverSocket.toString());
            
            while(true){
                try{ 
                 new Client(serverSocket.accept()).run();
                }
                catch(IOException e){
                 System.out.println(e.getMessage());
                }
            }
        } catch(IOException e){
            System.out.println("Server socket: " + e.getMessage());
        }
    }
}


Client.java
Код

package testServer;

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

public class Client extends Thread {
    
    private Socket clientSocket = null;
    private BufferedReader in = null;
    private PrintWriter out = null;
    
    private boolean hasName = false;
    private String player_name = "";
    
    public Client(Socket socket) {
        this.clientSocket = socket;
        
        //create I/O streams
        this.crateStreams();
        
        //start listening loop
        new Thread() {
            public void run(){
                String clientInput = "";
                try {
                    while ( (in != null) && (clientInput = in.readLine()) != null){
                        char first_char = clientInput.charAt(0);
                        if ((hasName) && (first_char != ' ')){
                            //something
                        } else if (first_char == (char)((int)0x01)) {  //register name
                            hasName = true;
                            player_name = clientInput.substring(2);
                            System.out.println(player_name + " connected");
                            
                            out.println("r");
                            out.flush();
                        }
                    }
                    //System.out.println(player_name + " disconnected");
                } catch(IOException e){
                    if (player_name == "") {
                        System.out.println("!!!!!!!!!! Client with no name disconnected !!!!!!!!!!");
                    } else {
                        System.out.println(player_name + " disconnected");
                    }
                };
            }
        }.start();
    }
    
    /**
     * Sets I/O streams for connected client
     */
    private void crateStreams() {
        //creating output stream
        try{
            out = new PrintWriter(clientSocket.getOutputStream(), true);
        }
        catch(IOException e){
         System.out.println("Error creating PrintWriter");
        }
        
        //creating input stream
        try{
            in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
        }
        catch(IOException e){
         System.out.println("Error creating BufferedReader");
        }
    }
}



Клиент

Main.java
Код

package emulator;

public class Main {
    
    /**
     * Server host
     */
    private static String host = "127.0.0.1";
    
    /**
     * Server port
     */
    private static int port = 6899;
    
    /**
     * how much client threads to start
     */
    private static int clients = 9;
    
    /**
     * how much times clients will reconnect to server
     */
    private static int reconnects = 1;
    
    /**    
     * clients name prefix
     */
    private static String name_prefix = "Client";

    /**
     * @param args not used
     */
    public static void main(String[] args) {
        int i = 0;
        
        for (i=0; i<clients; i++) {
            new Client(host, port, reconnects, name_prefix + " " + i).start();
        }
    }

}



Client.java
Код

package emulator;

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

public class Client extends Thread {
    
    private Socket         clientSocket = null;
    private PrintWriter    os           = null;
    private BufferedReader in           = null;
    
    private String host = "";
    private int    port = 0;
    private String name = "";
    private int reconnects = 0;
    
    private boolean accepted = false;
    
    public Client(String host, int port, int reconnects, String name) {
        this.host       = host;
        this.port       = port;
        this.name       = name;
        this.reconnects = reconnects;
    }
    
    public void run() {
        int i = 0;
        
        for (i=0; i<reconnects; i++) {
            try {
                clientSocket = new Socket(host, port);
                os = new PrintWriter(clientSocket.getOutputStream());
                in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
                if ( (os == null) || (in == null) ) {
                 System.out.println("Can't create I/O buffer");
                 System.exit(1);
                } else {
                 setPlayerName(name);
                }
                
                String serverInput = "";
                while( (in != null ) && (accepted == false) && (serverInput = in.readLine()) != null) {
                 if(serverInput.charAt(0) == 'r') {   //registered
                        accepted = true;
                        System.out.println("client " + name + " accepted");
                    }
                }
                if (in == null) {
                 System.out.println("connection error");
                }
                accepted = false;
                System.out.println(name + " disconnected");
                clientSocket.close();
            } catch(IOException e){
                System.out.println("Socket error: " + e.getLocalizedMessage() + "; " + host + ":" + port);
            }
        }
        
        System.exit(4);
    }
    
    public void setPlayerName(String s){
        if (os != null) {
            os.println(((char)((int)0x01)) + "|" + s);
            os.flush();
            System.out.println("Name sent: " + s);
        }
    }
}



Вот пример того, что выводится:

Код

!!!!!!!!!! Client with no name disconnected !!!!!!!!!!
Client 136 disconnected
!!!!!!!!!! Client with no name disconnected !!!!!!!!!!
Client 64 disconnected


Если чтото плохо обьяснил - говорите, постараюсь уточнить.

Автор: ivg 10.9.2008, 22:18
polakwilno, в последнем листинге удалите 62 строку:
Код
        System.exit(4);
 - это причина. Ну и до кучи поправьте код сервера: в классе Main замените 20 строку на 
Код
                 new Client(serverSocket.accept()).start();
; в классе Client метод run() сделайте методом класса Client. И this.crateStreams() вызывайте в run(), а не в конструкторе.

Автор: polakwilno 13.9.2008, 09:04
Цитата(ivg @ 10.9.2008,  22:18)
polakwilno, в последнем листинге удалите 62 строку:
Код
        System.exit(4);
 - это причина. Ну и до кучи поправьте код сервера: в классе Main замените 20 строку на 
Код
                 new Client(serverSocket.accept()).start();
; в классе Client метод run() сделайте методом класса Client. И this.crateStreams() вызывайте в run(), а не в конструкторе.

Эх... как это чаще всего и бывает, глупая ошибка...

Огромное спасибо, ivq

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)