2017-05-11 136 views
2

我正在開發一個軟件,與套接字,設置與服務器的連接(我安裝PgAdmin的數據庫)。 我創建客戶端e服務器代碼,他們完美運行,但我不知道如何通過套接字發送數據,當用戶做一些行動。該軟件就像一個社交網絡,用戶可以登錄並查看其他用戶記錄的信息和新聞。客戶端服務器多線程套接字

public class LoginForm { 

private JTextField EditUsername; 
private JTextField EditEmail; 

private static Client client; 

/** 
* Launch the application. 
*/ 
public static void main(String[] args) { 
    EventQueue.invokeLater(new Runnable() { 
     public void run() { 
      try { 
       client = new Client(); 
       client.connectToServer(); 
       LoginForm window = new LoginForm();     
       window.Loginframe.setVisible(true); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
    }); 
} 

/** 
* Create the application. 
*/ 
public LoginForm() { 
    initialize(); 
} 
... 
... 
String username = "USER"; client.SendToServer(username); 

這是我首先將客戶端連接到服務器的登錄表單。然後當我需要發送信息到服務器時,我不知道我需要做什麼!

import java.io.BufferedReader; 
import java.io.BufferedWriter; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.InputStreamReader; 
import java.io.OutputStream; 
import java.io.OutputStreamWriter; 
import java.io.PrintWriter; 
import java.net.InetAddress; 
import java.net.Socket; 
import java.net.UnknownHostException; 


public class Client { 

private BufferedReader in; 
private PrintWriter out; 

private static Socket socket; 
private static String number ="0" ; 


/** 
* Constructs the client by laying out the GUI and registering a 
* listener with the textfield so that pressing Enter in the 
* listener sends the textfield contents to the server. 
*/ 
public Client() { 
} 

public void connectToServer() throws IOException { 

    String host = "localhost"; 
    int port = 4000; 
    InetAddress address; 
    try { 
     address = InetAddress.getByName(host); 

     socket = new Socket(address, port); 

     //Send the message to the server 
     OutputStream os = socket.getOutputStream(); 
     OutputStreamWriter osw = new OutputStreamWriter(os); 
     BufferedWriter bw = new BufferedWriter(osw); 

     String number = "1"; 

     String sendMessage = number; 
     bw.write(sendMessage); 
     bw.flush(); 
     System.out.println("Message sent to the server : "+sendMessage); 

     //Get the return message from the server 
     InputStream is = socket.getInputStream(); 
     InputStreamReader isr = new InputStreamReader(is); 
     BufferedReader br = new BufferedReader(isr); 

     } 
    catch (Exception exception) 
    { 
     exception.printStackTrace(); 
    } 
    finally 
    { 
     //Closing the socket 
     try 
     { 
      socket.close(); 
     } 
     catch(Exception e) 
     { 
      e.printStackTrace(); 
     } 
    } 
public void SendToServer(String username){ 

} 
} 

所以這是客戶端接收字符串用戶,但我需要做什麼?創建另一個socket連接? 請幫我,套接字讓我發瘋。 我必須用戶插座(我知道RMI要好得多)

+1

轉問這個問題的信息:http://stackoverflow.com/questions/10332799/client-server-client-communication-using-sockets ?rq = 1 –

+0

只需以字符串,對象,字節的形式發送它 - 套接字具有輸出流,以便寫入它。這就像你會寫一些文件。 – Antoniossss

+0

但是當我創建登錄表單時,客戶端已經在運行?或者我在用戶點擊按鈕時運行它?另外我需要控制用戶的訪問權限,所以生成的套接字必須爲用戶創建一個會話 – dvdLucka

回答

2

非常簡短的回答:你需要做內connectToServer()方法private static Socket socket;private BufferedReader in;private PrintWriter out;局部變量。你的主要方法裏面還有private static Client client;

較長的答案:

客戶端服務器多線程的Socket

這是位值得商榷的,因爲沒有什麼比「多線程插座」,你要麼有一個「多線程服務器」或「單線程服務器」,這基本上意味着您的服務器能夠處理/處理併發連接,否則就不會。

現在,假設在服務器端你只有Socket clientSocket = serverSocket.accept();,然後你總是讀寫clientSocket對象,那麼你有「單線程服務器」,這基本上意味着,直到第一個請求沒有完成,你的第二個請求將保持在隊列中。如果你想創建一個「多線程服務器」,那麼你將每次創建一個新的線程,然後進行處理,這裏基本上你會有一個新的套接字代表一個獨特的客戶端連接。下面是一個示例「多線程服務器」代碼。

現在,在客戶端,您將指定您的服務器套接字詳細信息,您的做法socket = new Socket(address, port);,所以基本上將在您的「客戶端」打開一個新的套接字,在您的末端使用一些隨機端口號(請請注意,這不是一個隨機的服務器端口號,在您的端部,JVM將從操作系統獲取隨機「可用」端口號用於通信),並且該套接字對象將表示與服務器的唯一連接。那麼,您將訪問該套接字上的輸出流(將數據發送到服務器)和輸入流(從服務器讀取數據)。

現在,這裏是您的案例 - 在客戶端,您可以保持該套接字處於打開狀態,並將其用於所有服務器通信,如用戶點擊過一次,使用該套接字進行通信,然後再次使用該套接字下一次點擊等等(請注意,我只是把這個解釋),或者當你想要通信時,你會在你的最後創建一個新的套接字並進行通信。現在,通常用戶單擊GUI時將聯繫服務器和服務器進程,以便在新線程中請求,因此您的服務器(您要與服務器通信的服務器)通信代碼將在新線程中運行,並在您的case code in connectToServer(),只有你需要確保每次你在服務器端創建一個新的套接字而不是靜態的,併爲每個請求重複使用相同的套接字。

現在,這是您正在做的原始案例,如果您使用Spring或其他框架/ API,那麼您可以免費獲得連接池。

因此,這是客戶端接收字符串用戶,但我需要 辦?創建另一個socket連接?

是的,你應該每次創建一個新的客戶端套接字並使用它,要麼隱式地要麼通過創建一個新的線程來進行通信,我已經在上面解釋了你的情況。總的來說,每次你應該有一個新的套接字來與服務器進行通信。

請幫幫我,套接字讓我發瘋。

不要擔心只是瞭解基本,你會沒事的。最好是閱讀this或完成trail本身。

我必須用戶插座(我知道RMI要好得多)

你不能比較喜歡這個,到底是否是RMI,CORBA,RPC等等,等等,將有在客戶端是一個套接字,並且在服務器端會有一個套接字。以防萬一 - 服務器端套接字+客戶端套接字=服務器和客戶端之間的唯一連接。

同 「多線程服務器」 代碼:

import java.io.*; 
import java.net.InetAddress; 
import java.net.ServerSocket; 
import java.net.Socket; 
import java.net.SocketException; 
import java.net.SocketTimeoutException; 

import com.learn.Person; 

/** 
* @author himanshu.agrawal 
* 
*/ 
public class TestWebServer2 { 

    public static void main(String[] args) throws IOException { 
     startWebServer(); 
    } 


    /** 
    * test "backlog" in ServerSocket constructor 
test -- If <i>bindAddr</i> is null, it will default accepting 
    * connections on any/all local addresses. 
    * @throws IOException 
    */ 

    private static void startWebServer() throws IOException { 
     InetAddress address = InetAddress.getByName("localhost"); 
     ServerSocket serverSocket = new ServerSocket(8001, 1, address); 
     // if set it to 1000 (1 sec.) then after 1 second porgram will exit with SocketTimeoutException because server socket will only listen for 1 second. 
     // 0 means infinite 
     serverSocket.setSoTimeout(/*1*/0000); 

     while(true){ 
      /*Socket clientSocket = serverSocket.accept();*/ // a "blocking" call which waits until a connection is requested 
      System.out.println("1"); 
      TestWebServer2.SocketThread socketThread = new TestWebServer2().new SocketThread(); 
      try { 
       socketThread.setClientSocket(serverSocket.accept()); 
       Thread thread = new Thread(socketThread); 
       thread.start(); 
       System.out.println("2"); 
      } catch (SocketTimeoutException socketTimeoutException) { 
       System.err.println(socketTimeoutException); 
      } 
     } 

    } 

    public class SocketThread implements Runnable{ 

     Socket clientSocket; 

     public void setClientSocket(Socket clientSocket) throws SocketException { 
      this.clientSocket = clientSocket; 
      //this.clientSocket.setSoTimeout(2000); // this will set timeout for reading from client socket. 
     } 

     public void run(){ 
      System.out.println("####### New client session started." + clientSocket.hashCode() + " | clientSocket.getLocalPort(): " + clientSocket.getLocalPort() 
        + " | clientSocket.getPort(): " + clientSocket.getPort()); 
      try { 
       listenToSocket(); // create this method and you implement what you want to do with the connection. 
      } catch (IOException e) { 
       System.err.println("#### EXCEPTION."); 
       e.printStackTrace(); 
      } 
     } 


    } 

} 
+0

謝謝,我使用這個代碼服務器,它的工作原理! – dvdLucka

+0

很酷。那麼你有沒有找到你正在尋找的答案,或者你有什麼問題嗎? – hagrawal