![](/img/trans.png)
[英]thread overwritten when new socket connects (Server/Client) multithread java
[英]Client server multithread Socket
我正在开发带有Socket的软件,该软件可以设置与服务器的连接(我在其中安装了PgAdmin for DB)。 我创建了客户端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){
}
}
因此,这是接收字符串User的客户端,但我需要做什么? 创建另一个套接字连接? 请帮助我,插座使我发疯。 我必须使用用户套接字(我知道RMI更好)
答案很简短:您需要使private static Socket socket;
, private BufferedReader in;
和private PrintWriter out;
connectToServer()
方法内的局部变量。 另外, private static Client client;
在您的主要方法中。
更长的答案:
客户端服务器多线程套接字
这有点争议,因为没有像“多线程套接字”这样的东西,您将拥有“多线程服务器”或“单线程服务器”,这基本上意味着您的服务器将能够处理/处理并发连接,或者不会。
现在,假设在服务器端只有Socket clientSocket = serverSocket.accept();
然后您总是通过clientSocket
对象进行读写操作,那么您就拥有了“单线程服务器”,这基本上意味着,在第一个请求未完成之前,第二个请求将保留在队列中。 如果要创建“多线程服务器”,则每次都会创建一个新线程,然后进行处理,基本上,这里将有一个代表唯一客户端连接的新套接字。 下面是一个示例“多线程服务器”代码。
现在,在客户端,您将指定服务器套接字的详细信息,即套接字的方式socket = new Socket(address, port);
,因此基本上将在您的“客户端”使用一个末端的随机端口号在您的“客户端”处打开一个新的套接字(请注意,这不是一个随机的服务器端口号,在末端,JVM将从以下位置获取一个随机的“可用”端口号)用于通讯的OS),并且该套接字对象将代表与服务器的唯一连接。 因此,然后您将访问该套接字上的输出流(向服务器发送数据)和输入流(从服务器读取数据)。
现在,这是您要解决的问题-在客户端,您可以打开该套接字并将其用于所有服务器通信,例如用户单击一次,使用该套接字进行通信,然后再次将其用于下一次单击等。 (请注意,我只是在解释一下),或者,每当您要进行通信时,都将在末端创建一个新的套接字并进行通信。 现在,通常情况下,用户单击GUI会联系在新线程中请求的服务器和服务器进程,因此您的服务器(您要与之通信的服务器)通信代码将在新线程中运行,并且在您的connectToServer()
案例代码,仅需确保每次在服务器端创建一个新套接字时,都不必确保它是静态的,并且不会为每个请求重用同一套接字。
现在,这是您正在做的原始情况,如果您使用Spring或其他框架/ API,则可以免费获得连接池。
因此,这是接收字符串User的客户端,但我需要做什么? 创建另一个套接字连接?
是的,您应该每次都创建一个新的客户端套接字,并通过隐式或通过创建新线程进行通信的方式来使用该客户端套接字,上面已经说明了您的情况。 整个问题是,每次您都应该在终端使用一个新的套接字来与服务器通信时。
请帮助我,插座使我发疯。
不用担心,只要了解基本知识即可。 最好是读这个或完整线索本身。
我必须使用用户套接字(我知道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();
}
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.