2017-10-24 13 views
0

안녕하세요 StackOverflow의 커뮤니티,자바 + 라즈베리 파이 + ServerSocket의

은 내가 라즈베리 파이 제로에 java.net.ServerSocket을 출시 특정 질문이 있고 java.net.Socket로 연결합니다. RPi는 무선 액세스 포인트로 구성되므로 둘 이상의 노트북/태블릿이있는 WLAN을 통해 RPi에 연결할 수 있습니다. 목적은 RPi를 서버로 (별도의 네트워크 및 장치에서 실행중인 서버없이) 서버와 클라이언트 게임 (RPi에 연결할 수있는 클라이언트)으로 실행하는 것입니다.

  1. 내가 태블릿으로 무선 랜을 통해 RPI에 연결 :

    나는 그들이 항상 같은 결과를 보여 것을 증명하기 위해, 한 번 이상 모든 자세한 내용을 다음과 같은 네 가지 상황을 시도했다. 그런 다음 해당 타블렛에서 ServerSocket을 시작했습니다. 그 후 나는 그 타블렛상에서 Socket을 시작하고 그것을 ServerSocket에 연결했다. 연결이 작동하고 데이터가 양방향으로 전송되었습니다.

  2. 태블릿과 함께 WLAN을 통해 RPi에 연결되었습니다. 그런 다음 해당 타블렛에서 ServerSocket을 시작했습니다. 그 다음 RP0에 소켓 을 시작하고 그것을 내 태블릿에서 실행중인 ServerSocket에 연결했습니다. 연결이 작동하고 데이터가 양방향으로 전송되었습니다.

  3. 태블릿과 함께 WLAN을 통해 RPi에 연결되었습니다. 그런 다음 RPi에 ServerSocket 을 시작했습니다. 그 후 타블렛에서 Socket을 실행하고 내 RPi에서 실행중인 ServerSocket에 연결했습니다. 첫 번째 이상한 점은 ServerSocket의 IP가 0.0.0.0이라는 점이었습니다. 두 번째 문제는 클라이언트가 RPi에 연결하지 못하여 데이터를 전송할 수 없었기 때문입니다.

  4. 태블릿과 함께 WLAN을 통해 RPi에 연결되었습니다. 그런 다음 RP0에 ServerSocket 을 시작하고 지정된 IP 주소에 바인딩합니다. 그 후 타블렛에서 Socket을 실행하고이를 RPi에서 실행되는 ServerSocket에 연결합니다. ServerSocket이 지정된 IP 주소에 바인드하지 못했습니다. 따라서 Socket이 서버에 연결하지 못했고 따라서 데이터가 전송되지 않았습니다.

왜 ServerSocket에는 IP가 바인딩되지 않습니다 (0.0.0.0 제외)? IP 주소 0.0.0.0에 연결할 수없는 이유는 무엇입니까? Java로 RPi에서 ServerSocket을 실행하려면 어떻게해야합니까? 여기

내가 세 가지 상황에 사용되는 자바 소스 코드입니다 :

서버 :

import java.net.ServerSocket; 
import java.net.InetAddress; 
import java.net.Socket; 
import java.net.InetSocketAddress; 

import java.io.BufferedReader; 
import java.io.BufferedWriter; 
import java.io.InputStreamReader; 
import java.io.OutputStreamWriter; 

public class Server { 
    private  ServerSocket ss; 

    public static void main(String[] args) { 
     new Server();  // call the constructor 
    } 

    public Server() { 
     try { 
      ss = new ServerSocket(4444); // create the ServerSocket 
      new Thread(new Runnable() {  // create new Thread for listening to new clients 
       public void run() { 
        startAccept();   // run the accept-clients method 
       } 
      }).start();  // don't forget to start the thread 
      System.out.println(InetAddress.getLocalHost().getHostAddress()); // print the IP-Address 
      System.out.println("4444");  // print the Port 
     } catch (Exception e) { 
      e.printStackTrace();  // show exceptions 
     } 
    } 

    public void startAccept() { 
     while (true) {  // listen to new clients 
      try { 
       Socket so = ss.accept(); // accept the clients and create reader/writer 
       BufferedReader bure = new BufferedReader(new InputStreamReader(so.getInputStream())); 
       BufferedWriter buwr = new BufferedWriter(new OutputStreamWriter(so.getOutputStream())); 
       new Thread(new Runnable() {  // start new thread for reading from the client 
        public void run() { 
         readSocket(bure, buwr); // run the read/write method of the client 
        } 
       }).start();  // don't forget to start the thread 
      } catch (Exception e) { 
       e.printStackTrace();  // show exceptions 
      } 
     } 
    } 

    public void readSocket(BufferedReader bure, BufferedWriter buwr) { 
     while (true) {  // listen to all messages sent by the client 
      try { 
       String l1 = bure.readLine();   // read first line 
       System.out.println("Rec1: <"+l1+">"); // show it 
       String l2 = bure.readLine();   // read second line 
       System.out.println("Rec2: <"+l2+">"); // show it 
       buwr.write(l1+" + "+l2+" = "+(Integer.parseInt(l1)+Integer.parseInt(l2))+"\n"); 
       buwr.flush();  // convert both lines to integers and send the sum of them 
      } catch (Exception e) { 
       e.printStackTrace();  // show exceptions 
      } 
     } 
    } 
} 

클라이언트 :

import java.net.InetAddress; 
import java.net.InetSocketAddress; 
import java.net.Socket; 

import java.io.BufferedReader; 
import java.io.BufferedWriter; 
import java.io.InputStreamReader; 
import java.io.OutputStreamWriter; 

public class Client { 
    public static void main(String[] args) {  // start the program 
     try { 
      Socket so = new Socket();  // create an unbound socket 
      so.connect(new InetSocketAddress("0.0.0.0", 4444), 10000); 
       // bind socket to the IP-address printed by the Server and create reader/writer 
      BufferedReader bure = new BufferedReader(new InputStreamReader(so.getInputStream())); 
      BufferedWriter buwr = new BufferedWriter(new OutputStreamWriter(so.getOutputStream())); 
      buwr.write("7\n4\n"); // send 7 and 4, both followed by a new line 
      buwr.flush(); 
      System.out.println("Sent: <7\n4\n>"); // show the user what has been sent 
      System.out.println("Message from Server: "+bure.readLine()); // sum sent by the server 
      so.close();  // close socket 
     } catch (Exception e) { 
      e.printStackTrace(); // show exception 
     } 
    } 
} 

나는이 주제에 대한 사전에 어떤 도움 주셔서 감사합니다.

+1

"태블릿에서 소켓을 실행하고 ServerSocket에 연결했다고 말하면 무슨 뜻인지 정말로 이해하지 못합니다." 좀 더 자세히 설명해 주시겠습니까? 덧붙여 말하자면, "0.0.0.0"은 실제로 IP 번호가 아니라는 것입니다. 이것은 "listen on all interfaces"를 의미하는 리스닝 (서버) 소켓을 생성 할 때 사용됩니다. 클라이언트로 만들 때 실제 IP 번호를 사용해야합니다. –

+0

"소켓 실행"이란 서버의 IP로 클라이언트 소스 코드를 실행하면 연결이 Java 내부적으로 생성됩니다. 서버 소스 코드에서 "0.0.0.0"은 단지 대표적인 것입니다. "ServerSocket 실행"은 서버 소스 코드 실행을 의미합니다. –

+0

아마도 대표 코드가 아닌 실제 실행 코드를 포함한다면 이해하기가 쉽지 않을까요? 원래 질문에서 "왜 IP 주소 0.0.0.0에 연결할 수 없습니까?"라고 말했습니까? 이것은 IP 주소 0.0.0.0에 연결하려고하는 것처럼 보이지만 사실 의미가 없습니다. –

답변

0

마지막으로 나는 해결책을 스스로 찾았습니다.

핵심 문제는 RP0을 this 튜토리얼 (bridge-utils로 brigde를 설치하지 않고)으로 WAP으로 설정하는 것이 었습니다. 정적 IP 주소가 정의되어 있지 않으면 RPI에 액세스 할 수 없기 때문에 ServerSocket IP 주소로 바인드 할 수 없습니다.

sudo nano /etc/network/interfaces 

하고 파일의 끝에 다음 줄을 쓰기로

파일을 편집은/etc/네트워크/인터페이스 :

은 RPI WAP에 고정 IP 주소를 추가

그런 식으로 작동합니다.

auto wlan0 
iface wlan0 inet static 
    address 192.168.5.1 #Use own IP address here 
    netmask 255.255.255.0 

참고 :이 파일의 끝 부분에 빈 줄이있을 필요가있다. 고정 IP 주소가 /etc/dnsmasq.conf에 정의 된 범위 내에 있어야 할 필요는 없지만 서브넷 마스크가 맞는 경우에만 작동합니다 (필자의 경우 192.168.5.xxx 임).

다음 문제는 ServerSocket에 바인딩 된 IP를 알지 못했다는 것입니다. 나는

System.out.println(InetAddress.getLocalHost().getHostAddress()); 
System.out.println(ss.getInetAddress().getHostAddress()); 

를 호출하여 이상한 출력 (주석 참조)했고 ss.isBound()의 쿼리는 항상 true 돌아왔다. 이 문제에 대한 해결책은 ServerSocket을 RPi의 interfaces 파일에 정의 된 것과 동일한 특정 IP 주소에 바인딩하는 것입니다. 대신

ss = new ServerSocket(4444); 

를 호출 나는 그렇게 ServerSocket의이 내가 정의 된 고정 IP 주소에 바인딩 시작했다

ss = new ServerSocket(); 
ss.bind(new InetSocketAddress("192.168.5.1", 4444)); 

을 사용했다. 이제 서버에 메시지를 보낼 수있었습니다. 거기에서 메시지가 구문 분석되고 결과가 클라이언트로 다시 전송되었습니다.