2013-04-24 2 views
0

I'v은 ServerSocket의에 객체를 전송하는 멀티 스레드를 사용하는 코드를 가지고 (현재 및 localY을하지만, 로컬 네트워크에서 미래에)자바 소켓 ObjectOutputStream에 멀티 스레드

보내고 목적에 사용 :

public class SocketToAdapter { 

public static void writeObject(Object object) { 
    try { 

     give().writeUnshared(object); 

    } catch (IOException e) { 
     System.out.println(e.getMessage()); 
    } 
} 

static ObjectOutputStream give() { 
    Socket s = null; 
    try { 
     s = new Socket("localhost", 9990); 
     s.setTcpNoDelay(true); 
     return new ObjectOutputStream(s.getOutputStream()); 

    } catch (UnknownHostException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
    return null; 
} 

주요 방법 :

SocketToAdapter soc = new SocketToAdapter(); 

    thread1.setSocket(soc); 
    thread2.setSocket(soc); 
    thread3.setSocket(soc); 
    thread4.setSocket(soc); 
    thread5.setSocket(soc); 

    synchronized (valueExchanging) { 
     synchronized (soc) { 
      thread1.start(); 
      thread2.start(); 
      thread3.start(); 
      thread4.start(); 
      thread5.start(); 
     } 

valueExchanging 스레드 beetwen 데이터를 교환하는 데 사용되는 개체입니다. 스레드에서

실행 방법 :

public void run() { 
    try { 
     while (true) { 
      curr = new Object(pair, RandomUtil.getRandomExchange(), 
        RandomUtil.getRandomTurn()); 
      //not important Business Logic. 
          int v1 = valueExchanger.getExchangeInTread()+1; 
      int v2 = valueExchanger.getExchangeInTread()-100; 
      curr = new Object(pair, BigInteger.valueOf(v1), 
        BigInteger.valueOf(v2)); 
          // 
      SocketToAdapter.writeObject(curr); 
      valueExchanger.setExchangeInTread(v1); 
      Thread.sleep(0, 1); 
     } 
    } catch (InterruptedException iex) { 
    } 
} 

하지만 매우 느리게 작동합니다. 왜냐하면 필요할 때마다 Socket과 ObjectOutputStream을 생성하기 때문입니다. 나는 하나 개의 소켓 하나 OOS를 생성하고 이런 식으로 사용하려고 :

    { 
     Socket s = new Socket("localhost", 9990); 
     ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream()); } 

다음

oos.writeUnshared(object); 
oos.flush(); 
oos.writeUnshared(object); 

을 내가 OOS 두 번 다시 사용하려고하면하지만 난 소프트웨어는 발생 얻을 연결 중단 : 소켓 쓰기 오류 . 내가 얼마나 쓰레드를 쓰는지는 중요하지 않다.

초당 많은 수의 (예 : 100k) 물체를 보낼 수있는 가능성은 무엇입니까? 서버 측에서

내가 수행

Serwer.java :

ServerSocket ss; 
public static void pre()throws IOException, ClassNotFoundException { 
    ss = new ServerSocket(9990); 
    } 

public static Object start() throws IOException, ClassNotFoundException { 
    Object o = null; 
    Socket s = ss.accept(); 
    while (!s.isClosed()) { 
     ObjectInputStream ois = new ObjectInputStream(s.getInputStream()); 
     o = (Object) ois.readObject(); 
     ois.close(); 
     s.close(); 
    } 
    ss.close(); 
    return o; 

} 

"주요 방법"

while (true) { 

      try { 
       Serwer.pre(); 
       Object o = Serwer.start(); 
            //im do somethink with that object o. 
      } catch (IOException e1) { 
       e1.printStackTrace(); 
      } catch (ClassNotFoundException e) { 
       e.printStackTrace(); 
      } 
     } 
+0

왜 스레드를 시작할 때 soc에서 동기화합니까? 여러 스레드의 자원을 사용하는 경우 자원을 동기화해야합니다. 그리고 동기화 된 블록을 짧게 유지하십시오. 또는 심지어없이 지내보십시오. 동기화는 엄청난 성능 저하 요인입니다. – Fildor

+0

현재 동기화 (동기화되지 않은 상태에서 하나의 스레드를 사용하는 경우에도 성능에 문제가 있음)에서 동기화에 문제가 없습니다. – user1055201

+0

확실히 디자인에 더 많은 구조를 가져와야합니다. 죄책감은 없지만 한 곳에서 너무 많은 일을하지 않으려 고 노력하십시오 ... – Fildor

답변

0

이, 9990에서 사용자 서버 객체를 읽은 후 연결을 닫습니다 않거나 실패한거야? 이이 정리 된 후

, 당신은 전송되는 모든 개체에 대한 새로운 TCP 연결을 여는 클라이언트의 kryo

1

처럼 빠른 객체 시리얼 라이저를 사용하여 속도 직렬화를 최적화 볼 수 있습니다. TCP 연결을 설정하기 위해 많은 양의 오버 헤드가 있으므로 성능이 저하됩니다.

코드에서 서버는 단일 객체를 처리 한 후 연결을 닫는 것처럼 보입니다. 또한 전혀 작동하지 않는 것 같은 단일 연결을 처리 한 후 ServerSocket을 닫습니다. 서버 코드가 올바 릅니까? ServerSocket을 다시 시작할 서버 코드에서 다른 루프가 발생합니까?

각 클라이언트 스레드가 각각 서버에 별도의 연결을 가지고있는 Socket을 생성하는 것이 가장 좋은 방법 일 수 있습니다. 많은 양의 데이터를 푸시하고 여러 스레드를 사용하여이를 달성하려는 경우, 서버가 데이터를 처리하기 위해 여러 스레드를 필요로 할 가능성이 있습니다. 이 소켓은 한 번 생성되어야하며 모든 객체를 보내기 위해 재사용되어야합니다.

서버 쪽에서는 적절한 다중 스레드 TCP 서버를 만들고 싶습니다. 여기서 일반적인 아이디어는 SocketServer을 하나 생성하고 메서드를 while 루프로 호출하는 것입니다.accept()에서 반환되는 각 Socket에 대해 새 스레드를 실행하여 요청을 처리합니다. 예제는 다음에서 찾을 수 있습니다 : Multithreaded Server using TCP in Java

+0

전체 serversocket 생성보다는 accept()를 반복 할 수 있다는 것을 알고 계십니까? 당신도 다음 연결을 통해 얻을 각 소켓에 대한 스레드를 산란 simultanoulsy 여러 연결을 처리 할 수 ​​... – Fildor

0

java 소켓에는 경험이 없지만 s.setTcpNoDelay (true); 나는 당신의 프로그램이 TCP를 사용하여 패킷을 보내고, udp를 대신 사용해 봅니다. tcp 프로토콜은 패킷이 목적지에 도달했음을 보증하기위한 것이고, 이렇게하려면 무결성을 확인해야합니다. 반면에 udp는 패킷을 보내고 무결성에 관심이 없기 때문에 온라인 멀티 플레이어 게임에서 사용합니다.

+0

어떻게 TCP 대신 UDP를 사용할 수 있습니까? – user1055201

+0

@ user1055201 그것은 완전히 다른 이야기입니다. 어쩌면이 도움이 될 것입니다 : http://systembash.com/content/a-simple-java-udp-server-and-udp-client/ – Fildor

1

동일한 문제가있어서 간단한 소켓을 사용하여 문제를 해결했습니다. 이 클래스의 개체는 읽기/쓰기 작업이 필요한 지점에 있어야합니다.

public class Sender implements Closeable 
{ 
    private final Socket sock; 
    private final ObjectOutputStream out; 
    private ObjectInputStream in = null; 

    private final Object oLock = new Object(); 
    private final Object iLock = new Object(); 

    //optional 
    public boolean isClosed(){ 
    return sock.isClosed(); 
    } 

    //there is a better way to do this 
    public Socket getSocket(){ 

    return sock; 
    } 

    //use this to send data 
    public void send(Object o) throws IOException { 
    synchronized (oLock){ 
     getOOS().writeObject(o); 
    } 
    } 

    //use this to read data 
    public Object get() throws IOException { 
    synchronized (iLock){ 
     return getOIS().readObject(); 
    } 
    } 

    private ObjectOutputStream getOOS() { 
    return out; 
    } 

    //not the best way... but wouldn't work otherwise 
    private ObjectInputStream getOIS() throws IOException { 
    if(in == null) 
     in = new ObjectInputStream(sock.getInputStream()); 
    return in; 
    } 

    public Sender(Socket s) throws IOException { 
    sock = s; 
    out = new ObjectOutputStream(s.getOutputStream()); 
    //in = new ObjectInputStream(s.getInputStream()); 
    //getting the input and output stream gave me some weird deadlock 
    } 

    //optional 
    @Override 
    public String toString() { 
    return sock.toString(); 
    } 

    //flush and close if sock is not yet closed 
    @Override 
    public void close() throws IOException { 
    if(!sock.isClosed()){ 
     if(out != null) 
      out.flush(); 

     sock.close(); 
    } 
    } 
} 

이 하나와 서버 (보낸 사람이 서버에 연결된 소켓입니다) 클라이언트에서 잘하고 빠른 작동 (발신자 클라이언트와 연결된 소켓이다).

희망이 도움이됩니다.

그레이프 루핑