【问题标题】:Client server multithread Socket客户端服务器多线程Socket
【发布时间】:2017-10-10 22:57:37
【问题描述】:

我正在开发一个带有 Socket 的软件,它设置与服务器的连接(我在其中安装了 PgAdmin for DB)。 我创建了客户端和服务器代码,它们运行良好,但是当用户执行某些操作时,我不知道如何通过套接字发送数据。该软件就像一个社交网络,用户登录并查看来自其他登录用户的信息和新闻。

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){

 }
}

所以这是接收字符串用户的客户端,但我需要做什么???创建另一个套接字连接? 请帮助我,插座让我发疯。 我必须使用套接字(我知道 RMI 更好)

【问题讨论】:

  • 请参阅此问题以获取信息:stackoverflow.com/questions/10332799/…
  • 只需以字符串、对象、字节的形式发送它——套接字有输出流,所以写入它。就像你要写东西到文件一样。
  • 但是当我创建登录表单时,客户端已经在运行了?或者我在用户单击按钮时运行它?另外我需要控制用户访问,所以生成的套接字必须为用户创建一个会话
  • 这是您实施工作流程的工作。 Socket 只是用来发送数据的。

标签: java eclipse multithreading sockets


【解决方案1】:

非常简短的回答:您需要在 connectToServer() 方法中创建 private static Socket socket;private BufferedReader in;private PrintWriter out; 局部变量。另外,private static Client client; 在你的 main 方法中。

更长的答案:

客户端服务器多线程Socket

这有点值得商榷,因为没有像“多线程套接字”这样的东西,您将拥有“多线程服务器”或“单线程服务器”,这基本上意味着您的服务器将能够处理/处理并发连接,否则不会。

现在,假设在服务器端你只有Socket clientSocket = serverSocket.accept(); 然后你总是在clientSocket 对象上读写然后你有“单线程服务器”,这基本上意味着直到第一个请求没有完成,你的第二个请求将保留在队列中。如果你想创建一个“多线程服务器”,那么你每次都会创建一个新线程然后进行处理,这里基本上你会有一个代表唯一客户端连接的新套接字。下面是一个示例“多线程服务器”代码。

现在,在客户端,你将指定你的服务器套接字详细信息,你正在做socket = new Socket(address, port);的方式,所以基本上一个新的套接字将在你的“客户端”使用你端的一些随机端口号打开(请注意,这不是一个随机的服务器端口号,最终 JVM 会从操作系统获得一个随机的“可用”端口号用于通信),并且该套接字对象将代表与服务器的唯一连接。因此,您将访问该套接字上的输出流(将数据发送到服务器)和输入流(从服务器读取数据)。

现在,这是您的案例 - 在客户端,您可以保持该套接字打开并将其用于所有服务器通信,例如用户单击一次,使用该套接字进行通信,然后再次将其用于下一个单击等(请注意,我只是在解释),或者每当您需要通信时,您将在您的末端创建一个新的套接字并进行通信。现在,通常用户单击 GUI 将联系服务器和在新线程中请求的服务器进程,因此您的服务器(您想从服务器通信的那个)通信代码将在一个新线程中运行,并在您的connectToServer() 中的案例代码,您只需要确保每次在服务器端创建一个新套接字,而不是使其成为静态并为每个请求重用相同的套接字。

现在,这是您正在做的原始案例,如果您使用 Spring 或其他一些框架/API,那么您可以免费获得连接池。

所以这是接收字符串用户但我需要的客户端 做 ???创建另一个套接字连接?

是的,您应该每次都创建一个新的客户端套接字并使用它,无论是隐式还是通过创建一个新线程来进行通信,我已经在上面解释了您的情况;重点是每次你都应该有一个新的套接字来与服务器通信。

请帮帮我,插座快把我逼疯了。

别担心,只要了解基本的,你就会没事的。最好是阅读this 或完成trail 本身。

我必须使用套接字(我知道 RMI 更好)

不能这样比较,到底是RMI、CORBA、RPC等等等等,客户端都会有socket,服务器端也会有socket。以防万一 - 服务器端套接字 + 客户端套接字 = 服务器和客户端之间的唯一连接。

相同的“多线程服务器”代码:

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();
            }
        }


    }

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-04-18
    • 2014-12-21
    • 2011-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-17
    相关资源
    最近更新 更多