有三个文件(主函数文件,服务器文件和客户端文件)
将运行主函数文件,其中“-l”的存在确定如果“-l”不存在,它将表现为服务器还是客户端。
运行服务器的命令参数是
java DirectMessengerCombined -l 3000
运行客户端的命令参数是
java DirectMessengerCombined 3000
有四个线程(一个用于在客户端接收消息,一个用于在客户端发送消息,一个用于在服务器端接收消息,一个用于在服务器端发送消息)
Screenshot of running program (client on right, server on left)
屏幕截图的问题是“客户端我是服务器的客户端”消息未发送到客户端。
服务器代码:
import java.io.*;
import java.net.*;
import java.util.*;
import javax.imageio.IIOException;
//import static java.nio.charset.StandardCharsets.*;
public class DirectMessengerServer
{
private static Socket socket;
boolean KeepRunning = true;
void ServerRun(String[] args)
{
Thread ServerRecieve = new Thread ()
{
public void run ()
{
System.out.println("Server recieve thread is now running");
try
{
System.out.println("Try block begins..");
int port_number1= Integer.valueOf(args[1]);
System.out.println("Port number is: " + port_number1);
ServerSocket serverSocket = new ServerSocket(port_number1);
//SocketAddress addr = new InetSocketAddress(address, port_number1);
System.out.println( "Listening for connections on port: " + ( port_number1 ) );
while(KeepRunning)
{
//Reading the message from the client
socket = serverSocket.accept();
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String MessageFromClient = br.readLine();
System.out.println("Message received from client: "+ MessageFromClient);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally
{
}
}
};ServerRecieve.start();
Thread ServerSend = new Thread ()
{
public void run ()
{
System.out.println("Server sending thread is now running");
try
{
//Send the message to the server
OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
//creating message to send from standard input
String newmessage = "";
try
{
// input the message from standard input
BufferedReader input= new BufferedReader(
new InputStreamReader(System.in));
String line = "";
line= input.readLine();
newmessage += line + " ";
}
catch ( Exception e )
{
System.out.println( e.getMessage() );
}
String sendMessage = newmessage;
bw.write(sendMessage + "\n");
bw.flush();
System.out.println("Message sent to client: "+sendMessage);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally
{
}
}
};ServerSend.start();
}
}
客户代码:
import java.io.*;
import java.net.*;
import java.util.*;
import static java.nio.charset.StandardCharsets.*;
public class DirectMessengerClient
{
boolean KeepRunning = true;
private static Socket socket;
//static String[] arguments;
//public static void main(String[] args)
//{
// arguments = args;
//}
public DirectMessengerClient()
{
//System.out.println("test.");
}
public void ClientRun(String[] args)
{
Thread ClientSend = new Thread ()
{
public void run()
{
System.out.println("Client sending thread is now running");
try
{
System.out.println("Try block begins..");
String port_number1= args[0];
System.out.println("Port number is: " + port_number1);
int port = Integer.valueOf(port_number1);
System.out.println("Listening for connections..");
System.out.println( "Listening on port: " + port_number1 );
while(KeepRunning)
{
String host = "localhost";
InetAddress 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);
//creating message to send from standard input
String newmessage = "";
try
{
// input the message from standard input
BufferedReader input= new BufferedReader(
new InputStreamReader(System.in));
String line = "";
line= input.readLine();
newmessage += line + " ";
}
catch ( Exception e )
{
System.out.println( e.getMessage() );
}
String sendMessage = newmessage;
bw.write(sendMessage + "\n");
bw.flush();
System.out.println("Message sent to server: "+sendMessage);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally
{
}
//finally
// {
//}
}
}; ClientSend.start();
Thread ClientRecieve = new Thread ()
{
public void run()
{
while(KeepRunning)
{
try
{
System.out.println("Client Reieving thread is now running");
//Get the return message from the server
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String MessageFromServer = br.readLine();
System.out.println("Message received from server: " + MessageFromServer);
if(MessageFromServer.equals(""))
{
KeepRunning=false;
System.out.println("Shutting down");
System.exit(0);
socket.close();
}
if(MessageFromServer.equals(null))
{
KeepRunning=false;
System.out.println("Shutting down");
System.exit(0);
socket.close();
}
if(MessageFromServer=="")
{
KeepRunning=false;
System.out.println("Shutting down");
System.exit(0);
socket.close();
}
if(MessageFromServer==null)
{
KeepRunning=false;
System.out.println("Shutting down");
System.exit(0);
socket.close();
}
if(MessageFromServer=="\n")
{
KeepRunning=false;
System.out.println("Shutting down");
System.exit(0);
socket.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally
{
}
}
}
};ClientRecieve.start();
}
}
主要功能文件代码:
public class DirectMessengerCombined
{
public static void main(String[] args)
{
DirectMessengerClient Client1 = new DirectMessengerClient();
DirectMessengerServer Server1 = new DirectMessengerServer();
for (int i = 0; i < args.length; i++)
{
if(!args[0].equals("-l"))
{
Client1.ClientRun(args);
}
switch (args[0].charAt(0))
{
case '-':
if(args[0].equals("-l"))
{
Server1.ServerRun(args);
}
}
i=args.length + 20;
}
}
}
我的问题是如何使服务器和客户端都能够连续发送和接收消息(在客户端发送工作,但接收不起作用)
答案 0 :(得分:0)
一种好方法是分离接受连接和操作连接,这是大多数服务器所做的。
例如,您接受主线程上的传入连接,并使用执行程序服务对线程池中的连接进行操作:
AtomicBoolean running = new AtomicBoolean();
ExecutorService pool = Executors.newFixedThreadPool(10;
ServerSocket listen = new ServerSocket(11000);
while(running.get()){
Socket socket = listen.accept();
pool.submit(() -> {
try(InputStream is = socket.getInputStream();
OutputStream os = socket.getOutputStream()){
//put I/O logic here
} catch (IOException e) {
e.printStackTrace();
}
});
}
在此示例中,输入和输出在同一个线程中处理,如果要同时读写,则提交两个任务,一个操作输入,另一个输出。重要提示:只有在接受连接后才能获得套接字。
如果要彼此进行线程通信,可以使用共享对象(即消息队列)执行此操作。但是这个数据结构必须是线程安全,而JDK提供了很多这样的数据结构:
例如
final ConcurrentLinkedDeque<String> queue = new ConcurrentLinkedDeque<>();
while(running.get()){
Socket socket = listen.accept();
pool.submit(() -> {
try(BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()))){
while(socket.isConnected()){
queue.push(reader.readLine());
}
} catch (IOException e) {
e.printStackTrace();
}
});
pool.submit(() -> {
try(OutputStream os = socket.getOutputStream()){
if(!queue.isEmpty()){
os.write(queue.pop().getBytes());
}
} catch (IOException e) {
e.printStackTrace();
}
});
}
对于客户来说基本相同,只是你不接受连接而是打开一个