- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我在这里进行了很多搜索,但没有找到任何符合我需要的内容。
我在客户端/服务器应用程序方面不是那么专家,这是我第一次尝试,所以,如果我犯了一些错误或者提出了愚蠢的问题,请耐心等待。
现在,回到我的问题..
我需要构建一个多客户端/服务器应用程序。
服务器端应该是客户端的简单管理器。
例如:
另一方面,客户端是一个复杂的应用程序(至少对于用户而言),应该发送到服务器:
所以,我的问题基本上是这样的:如何处理服务器与特定客户端的通信?我的意思是,我已经启动了服务器,并且我只为一个客户端更改配置。
我想我需要以某种方式存储客户端..比如在数组(List
)中,但我不知道这是否是正确的方法。(基本上我不知道Socket
和ServerSocket
类是如何工作的..如果这可以帮助您更好地理解)
此外,当服务器启动并监听时......需要更新 GUI 以显示新连接的客户端,因此我需要某种类型的服务器监听器,以便在新客户端显示时将操作触发回界面向上?(很多人使用 而(真){ 套接字=服务器.accept(); }方法,但这对我来说听起来不太聪明..)
这是基本的 Client.java 和 Server.java 文件,其中包含我根据大量 Google 搜索编写的客户端和服务器基本功能。
但是下面的所有代码并不能满足我的所有需求..
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;
public class Client extends Socket {
private static Client instance = null;
/**
* The main init() function for this class, to create a Singleton instance for the Client
*
* @param host
* The host of the Server
* @param port
* The port of the Server
* @return The Client instance that is a new instance if no one exists previusly,
* otherwise an older instance is returned
* @throws UnknownHostException
* @throws IOException
*/
public static Client init( String host, Integer port ) throws UnknownHostException, IOException
{
if ( Client.instance == null )
Client.instance = new Client( host, port );
return Client.instance;
}
/**
* Default Constructor made private so this class can only be instantiated by the
* singleton init() function.
*
* @param host
* The host of the server
* @param port
* The port of the server
* @throws UnknownHostException
* @throws IOException
*/
private Client( String host, Integer port ) throws UnknownHostException, IOException
{
super( host, port );
}
/**
* Function used to send a file to the server.
* When this function fires, the Client class start sending a file to the server.
* Internally this function handles the filesize, and some other file information
* that the server needs to store the file in the correct location
*
* @param filename
* The filename of the file that will be sended to the server
*/
public void sendFile( String filename ) throws FileNotFoundException, IOException
{
// The file object from the filename
File file = new File( filename );
// A string object to build an half of the message that will be sent to the exceptions
StringBuilder exception_message = new StringBuilder();
exception_message.append( "The File [" ).append( filename ).append( "] " );
// Check if the file exists
if ( !file.exists() )
throw new FileNotFoundException( exception_message + "does not exists." );
// Check if the file size is not empty
if ( file.length() <= 0 )
throw new IOException( exception_message + "has zero size." );
// Save the filesize
Long file_size = file.length();
// Check if the filesize is something reasonable
if ( file_size > Integer.MAX_VALUE )
throw new IOException( exception_message + "is too big to be sent." );
byte[] bytes = new byte[file_size.intValue()];
FileInputStream fis = new FileInputStream( file );
BufferedInputStream bis = new BufferedInputStream( fis );
BufferedOutputStream bos = new BufferedOutputStream( this.getOutputStream() );
int count;
// Loop used to send the file in bytes group
while ( ( count = bis.read( bytes ) ) > 0 )
{
bos.write( bytes, 0, count );
}
bos.flush();
bos.close();
fis.close();
bis.close();
}
/**
* Function used to send string message from client to the server
*
* @param message
* The string message the server should get
* @throws IOException
*/
public void sendMessage( String message ) throws IOException
{
OutputStream os = this.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter( os );
BufferedWriter bw = new BufferedWriter( osw );
bw.write( message );
bw.flush();
}
/**
* Function used to get a message from the Server
*
* @return The message the server sent back
* @throws IOException
*/
public String getMessage() throws IOException
{
InputStream is = this.getInputStream();
InputStreamReader isr = new InputStreamReader( is );
BufferedReader br = new BufferedReader( isr );
String message = br.readLine();
return message;
}
}
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.net.ServerSocket;
import java.net.Socket;
public class Server extends ServerSocket {
private static Server instance = null;
private Socket socket = null;
/**
*
* @param port
* @return
* @throws IOException
*/
public static Server init( Integer port ) throws IOException
{
if ( Server.instance == null )
Server.instance = new Server( port );
return Server.instance;
}
/**
*
* @param port
* @throws IOException
*/
private Server( Integer port ) throws IOException
{
super( port );
// Maybe this is something that needs to be improved
while ( true )
this.socket = this.accept();
}
/**
*
* @param message
* @throws IOException
*/
public void sendMessage( String message ) throws IOException
{
OutputStream os = this.socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter( os );
BufferedWriter bw = new BufferedWriter( osw );
bw.write( message );
bw.flush();
}
/**
*
* @return
* @throws IOException
*/
public String getMessage() throws IOException
{
InputStream is = this.socket.getInputStream();
InputStreamReader isr = new InputStreamReader( is );
BufferedReader br = new BufferedReader( isr );
String message = br.readLine();
return message;
}
}
嗯..请为我的英语道歉..请。
最佳答案
你的问题让我很好奇,现代的 java 方法会是什么样子。当我开始尝试套接字时,我也遇到了一些问题,所以这里有一个小例子应该可以帮助您解决问题。
服务器在自己的“线程”中处理每个客户端,你可以说这是基本的客户端/服务器架构。但我用的是新的Callable<V>
而不是线程。
我没有延长Socket
也不ServerSocket
。我以前从来没有见过这个。我认为在这种情况下,最好选择组合而不是继承。它为您提供了更多控制权,因为您可以委托(delegate)您喜欢的内容和方式。
有关更多信息,我建议您查看oracle tutorials .
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Arrays;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ClientServerExample
{
private final static int PORT = 1337;
private final static String LOOPBACK = "127.0.0.1";
public static void main(String[] args) throws IOException
{
ExecutorService se = Executors.newSingleThreadExecutor();
se.submit(new Server(PORT, 5));
ExecutorService ce = Executors.newFixedThreadPool(3);
for (String name : Arrays.asList("Anton", "John", "Lisa", "Ben", "Sam", "Anne"))
ce.submit(new Client(name, LOOPBACK, PORT));
ce.shutdown(); while (!ce.isTerminated()) {/* wait */}
se.shutdown();
}
}
class Client implements Callable<Void>
{
private final String name;
private final String ip;
private final int port;
public Client(String name, String ip, int port)
{
this.name = name;
this.ip = ip;
this.port = port;
}
@Override
public Void call() throws Exception
{
Socket s = new Socket(ip, port);
PrintWriter out = new PrintWriter(s.getOutputStream(), true);
out.println("Hi, I'm " + name + "!");
out.close();
s.close();
return null;
}
}
class Server implements Callable<Void>
{
private final int port;
private final int clients;
private final ExecutorService e;
public Server(int port, int clients)
{
this.port = port;
this.clients = clients;
this.e = Executors.newFixedThreadPool(clients);
}
@Override
public Void call() throws Exception
{
ServerSocket ss = new ServerSocket(port);
int client = 0;
while (client < clients)
{
e.submit(new ClientHandler(client++, ss.accept()));
}
ss.close();
e.shutdown(); while (!e.isTerminated()) {/* wait */}
return null;
}
}
class ClientHandler implements Callable<Void>
{
private int client;
private Socket s;
public ClientHandler(int client, Socket s)
{
this.client = client;
this.s = s;
}
@Override
public Void call() throws Exception
{
BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
String fromClient;
while ((fromClient = in.readLine()) != null)
{
System.out.println("FROM CLIENT#" + client + ": " + fromClient);
}
in.close();
s.close();
return null;
}
}
输出
FROM CLIENT#0: Hi, I'm John!
FROM CLIENT#2: Hi, I'm Sam!
FROM CLIENT#1: Hi, I'm Ben!
FROM CLIENT#3: Hi, I'm Anne!
FROM CLIENT#4: Hi, I'm Anton!
关于java - 如何处理客户端/服务器应用程序以发送消息和/或文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18637322/
我正在通过 labrepl 工作,我看到了一些遵循此模式的代码: ;; Pattern (apply #(apply f %&) coll) ;; Concrete example user=> (a
我从未向应用商店提交过应用,但我会在不久的将来提交。 到目前为止,我对为 iPhone 而非 iPad 进行设计感到很自在。 我了解,通过将通用PAID 应用放到应用商店,客户只需支付一次就可以同时使
我有一个应用程序,它使用不同的 Facebook 应用程序(2 个不同的 AppID)在 Facebook 上发布并显示它是“通过 iPhone”/“通过 iPad”。 当 Facebook 应用程序
我有一个要求,我们必须通过将网站源文件保存在本地 iOS 应用程序中来在 iOS 应用程序 Webview 中运行网站。 Angular 需要服务器来运行应用程序,但由于我们将文件保存在本地,我们无法
所以我有一个单页客户端应用程序。 正常流程: 应用程序 -> OAuth2 服务器 -> 应用程序 我们有自己的 OAuth2 服务器,因此人们可以登录应用程序并获取与用户实体关联的 access_t
假设我有一个安装在用户设备上的 Android 应用程序 A,我的应用程序有一个 AppWidget,我们可以让其他 Android 开发人员在其中以每次安装成本为基础发布他们的应用程序推广广告。因此
Secrets of the JavaScript Ninja中有一个例子它提供了以下代码来绕过 JavaScript 的 Math.min() 函数,该函数需要一个可变长度列表。 Example:
当我分别将数组和对象传递给 function.apply() 时,我得到 NaN 的 o/p,但是当我传递对象和数组时,我得到一个数字。为什么会发生这种情况? 由于数组也被视为对象,为什么我无法使用它
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界. 这篇CFSDN的博客文章ASP转换格林威治时间函数DateDiff()应用由作者收集整理,如果你
我正在将列表传递给 map并且想要返回一个带有合并名称的 data.frame 对象。 例如: library(tidyverse) library(broom) mtcars %>% spl
我有一个非常基本的问题,但我不知道如何实现它:我有一个返回数据框,其中每个工具的返回值是按行排列的: tmp<-as.data.frame(t(data.frame(a=rnorm(250,0,1)
我正在使用我的 FB 应用创建群组并邀请用户加入我的应用群组,第一次一切正常。当我尝试创建另一个组时,出现以下错误: {"(OAuthException - #4009) (#4009) 在有更多用户
我们正在开发一款类似于“会说话的本”应用程序的 child 应用程序。它包含大量用于交互式动画的 JPEG 图像序列。 问题是动画在 iPad Air 上播放正常,但在 iPad 2 上播放缓慢或滞后
我关注 clojure 一段时间了,它的一些功能非常令人兴奋(持久数据结构、函数式方法、不可变状态)。然而,由于我仍在学习,我想了解如何在实际场景中应用,证明其好处,然后演化并应用于更复杂的问题。即,
我开发了一个仅使用挪威语的应用程序。该应用程序不使用本地化,因为它应该仅以一种语言(挪威语)显示。但是,我已在 Info.plist 文件中将“本地化 native 开发区域”设置为“no”。我还使用
读完 Anthony's response 后上a style-related parser question ,我试图说服自己编写单体解析器仍然可以相当紧凑。 所以而不是 reference ::
multicore 库中是否有类似 sapply 的东西?还是我必须 unlist(mclapply(..)) 才能实现这一点? 如果它不存在:推理是什么? 提前致谢,如果这是一个愚蠢的问题,我们深表
我喜欢在窗口中弹出结果,以便更容易查看和查找(例如,它们不会随着控制台继续滚动而丢失)。一种方法是使用 sink() 和 file.show()。例如: y <- rnorm(100); x <- r
我有一个如下所示的 spring mvc Controller @RequestMapping(value="/new", method=RequestMethod.POST) public Stri
我正在阅读 StructureMap关于依赖注入(inject),首先有两部分初始化映射,具体类类型的接口(interface),另一部分只是实例化(请求实例)。 第一部分需要配置和设置,这是在 Bo
我是一名优秀的程序员,十分优秀!