简体   繁体   English

客户端服务器多线程套接字

[英]Client server multithread Socket

i'm developing a software that with a Socket, sets a connection with a server(where I installed PgAdmin for DB). 我正在开发带有Socket的软件,该软件可以设置与服务器的连接(我在其中安装了PgAdmin for DB)。 I create the client e server code and they run perfectly but I don't know how to send data via socket when the user do some action. 我创建了客户端e服务器代码,它们可以完美运行,但是当用户执行某些操作时,我不知道如何通过套接字发送数据。 The software is like a social network, where users login and see their info and news from the other users that are logged. 该软件就像一个社交网络,用户可以在其中登录并查看其他登录用户的信息和新闻。

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

this is my login form where firstly connect client to server. 这是我的登录表单,首先将客户端连接到服务器。 Then when I need to send info to server I don't know what i need to do !!! 然后,当我需要向服务器发送信息时,我不知道该怎么做!

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

 }
}

So this is the client that receive the string User but What I need to do ??? 因此,这是接收字符串User的客户端,但我需要做什么? create another socket connection ? 创建另一个套接字连接? Please help me, sockets are driving me mad. 请帮助我,插座使我发疯。 I must user socket(I know RMI is much better) 我必须使用用户套接字(我知道RMI更好)

Very short answer: you need to make private static Socket socket; 答案很简短:您需要使private static Socket socket; , private BufferedReader in; private BufferedReader in; and private PrintWriter out; private PrintWriter out; local variables inside connectToServer() method. connectToServer()方法内的局部变量。 Also, private static Client client; 另外, private static Client client; inside your main method. 在您的主要方法中。

Longer answer: 更长的答案:

Client server multithread Socket 客户端服务器多线程套接字

This is bit debatable because there is nothing like "multithreaded socket", you will either have a "multi-threaded server" or "single-threaded server", which basically means that either your server would capable of handling/processing concurrent connections or it would be not. 这有点争议,因为没有像“多线程套接字”这样的东西,您将拥有“多线程服务器”或“单线程服务器”,这基本上意味着您的服务器将能够处理/处理并发连接,或者不会。

Now, suppose at server side you have just Socket clientSocket = serverSocket.accept(); 现在,假设在服务器端只有Socket clientSocket = serverSocket.accept(); and then you are always reading and writing over clientSocket object then you have "single-threaded server" which basically means that until first request is not completed, your second request would remain in queue. 然后您总是通过clientSocket对象进行读写操作,那么您就拥有了“单线程服务器”,这基本上意味着,在第一个请求未完成之前,第二个请求将保留在队列中。 If you want to create a "multi-threaded server" then you will create a new thread each time and then do the processing, here basically you would have a new socket representing a unique client connection. 如果要创建“多线程服务器”,则每次都会创建一个新线程,然后进行处理,基本上,这里将有一个代表唯一客户端连接的新套接字。 Below is a sample "multi-threaded server" code. 下面是一个示例“多线程服务器”代码。

Now, coming at client side, you will specify your server socket details, the way you are doing socket = new Socket(address, port); 现在,在客户端,您将指定服务器套接字的详细信息,即套接字的方式socket = new Socket(address, port); , so basically a new socket will be opened at your "client side" using some random port number at your end (please note that this is not a random server port number, at your end JVM will get a random "available" port number from OS for communication), and that socket object would represent a unique connection with the server. ,因此基本上将在您的“客户端”使用一个末端的随机端口号在您的“客户端”处打开一个新的套接字(请注意,这不是一个随机的服务器端口号,在末端,JVM将从以下位置获取一个随机的“可用”端口号)用于通讯的OS),并且该套接字对象将代表与服务器的唯一连接。 So, then you will access output stream on that socket (to send data to server) and input stream (to read data from server). 因此,然后您将访问该套接字上的输出流(向服务器发送数据)和输入流(从服务器读取数据)。

Now, here is the catch of your case - at client side, either you can keep that socket open and use it for all server communications, like user has clicked once, communicate using that socket, and then again use that for next click etc. (please note that I am just putting this to explain), OR whenever you want a communication you will create a new socket at your end and communicate. 现在,这是您要解决的问题-在客户端,您可以打开该套接字并将其用于所有服务器通信,例如用户单击一次,使用该套接字进行通信,然后再次将其用于下一次单击等。 (请注意,我只是在解释一下),或者,每当您要进行通信时,都将在末端创建一个新的套接字并进行通信。 Now, typically a user click at GUI will contact server and server processes that request in a new thread, so your server (the one with which you want to communicate from your server) communication code will be ran in a new thread, and in your case code in connectToServer() , only thing you need to make sure that each time you are creating a new socket at your server's end and not making it static and reusing same socket for each request. 现在,通常情况下,用户单击GUI会联系在新线程中请求的服务器和服务器进程,因此您的服务器(您要与之通信的服务器)通信代码将在新线程中运行,并且在您的connectToServer()案例代码,仅需确保每次在服务器端创建一个新套接字时,都不必确保它是静态的,并且不会为每个请求重用同一套接字。

Now, this is the raw case you are doing, if you use Spring or some other frameworks/API then you can get connection pooling for free. 现在,这是您正在做的原始情况,如果您使用Spring或其他框架/ API,则可以免费获得连接池。

So this is the client that receive the string User but What I need to do ??? 因此,这是接收字符串User的客户端,但我需要做什么? create another socket connection ? 创建另一个套接字连接?

Yes, you should create a new client socket each time and use that, either implicitly or by creating a new thread to do communication, I have explained above how is your case; 是的,您应该每次都创建一个新的客户端套接字,并通过隐式或通过创建新线程进行通信的方式来使用该客户端套接字,上面已经说明了您的情况。 and whole point is that each time you should have a new socket at your end for communicating with server. 整个问题是,每次您都应该在终端使用一个新的套接字来与服务器通信时。

Please help me, sockets are driving me mad. 请帮助我,插座使我发疯。

Don't worry just understand basic and you will be fine. 不用担心,只要了解基本知识即可。 Best is to read this or complete trail itself. 最好是读这个或完整线索本身。

I must user socket(I know RMI is much better) 我必须使用用户套接字(我知道RMI更好)

You can't compare like this, in the end whether it is RMI, CORBA, RPC etc. etc., there will be a socket at client side and there will be a socket at server side. 您无法像这样进行比较,最后无论是RMI,CORBA,RPC等,在客户端都有一个套接字,而在服务器端会有一个套接字。 Just in case - server side socket + client side socket = unique connection between server and client. 以防万一-服务器端套接字+客户端套接字=服务器和客户端之间的唯一连接。

Same "multi-threaded server" code: 相同的“多线程服务器”代码:

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


    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM