我得到的代码使用多线程将对象发送到ServerSocket(目前是localy,但将来在本地网络中)
用于发送对象:
public class SocketToAdapter {
public static void writeObject(Object object) {
try {
give().writeUnshared(object);
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
static ObjectOutputStream give() {
Socket s = null;
try {
s = new Socket("localhost", 9990);
s.setTcpNoDelay(true);
return new ObjectOutputStream(s.getOutputStream());
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
主要方法:
SocketToAdapter soc = new SocketToAdapter();
thread1.setSocket(soc);
thread2.setSocket(soc);
thread3.setSocket(soc);
thread4.setSocket(soc);
thread5.setSocket(soc);
synchronized (valueExchanging) {
synchronized (soc) {
thread1.start();
thread2.start();
thread3.start();
thread4.start();
thread5.start();
}
valueExchanging是一个用于交换beetwen线程数据的Object。
从线程运行方法:
public void run() {
try {
while (true) {
curr = new Object(pair, RandomUtil.getRandomExchange(),
RandomUtil.getRandomTurn());
//not important Business Logic.
int v1 = valueExchanger.getExchangeInTread()+1;
int v2 = valueExchanger.getExchangeInTread()-100;
curr = new Object(pair, BigInteger.valueOf(v1),
BigInteger.valueOf(v2));
//
SocketToAdapter.writeObject(curr);
valueExchanger.setExchangeInTread(v1);
Thread.sleep(0, 1);
}
} catch (InterruptedException iex) {
}
}
这很有效但很慢。因为我每次需要时都会创建Socket和ObjectOutputStream。我尝试创建一个Socket和一个OOS并像这样使用它:
{
Socket s = new Socket("localhost", 9990);
ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream()); }
然后
oos.writeUnshared(object);
oos.flush();
oos.writeUnshared(object);
但如果我第二次尝试重用oos我得到软件导致连接中止:套接字写入错误。无论我使用多少线程。
我需要的是每秒发送许多(例如100k)对象,任何sugesstions的可能性吗?
在服务器端我做:
Serwer.java:
ServerSocket ss;
public static void pre()throws IOException, ClassNotFoundException {
ss = new ServerSocket(9990);
}
public static Object start() throws IOException, ClassNotFoundException {
Object o = null;
Socket s = ss.accept();
while (!s.isClosed()) {
ObjectInputStream ois = new ObjectInputStream(s.getInputStream());
o = (Object) ois.readObject();
ois.close();
s.close();
}
ss.close();
return o;
}
“主要方法”
while (true) {
try {
Serwer.pre();
Object o = Serwer.start();
//im do somethink with that object o.
} catch (IOException e1) {
e1.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
答案 0 :(得分:1)
在客户端,它为每个发送的对象打开一个新的TCP连接。这会破坏性能,因为建立TCP连接会产生大量开销。
从您的代码中,服务器在处理单个对象后看起来正在关闭连接。在处理单个连接之后它也会关闭ServerSocket
,这似乎根本不起作用。提供的服务器代码是否正确?是否在服务器代码中出现了另一个循环,它将启动另一个ServerSocket
?
最好的方法可能是让每个客户端线程创建自己的Socket
,每个客户端都有一个与服务器的单独连接。如果您尝试推送大量数据并使用多个线程来实现这一点,那么服务器很可能需要多个线程来处理数据。这些套接字应该只创建一次并重复使用以发送所有对象。
在服务器端,您将需要创建适当的多线程TCP服务器。这里的一般想法是创建一个SocketServer
并在accept()
循环中调用其while
方法。对于从Socket
返回的每个accept()
,您将启动一个新线程来处理请求。可以在此处找到一个示例:Multithreaded Server using TCP in Java
答案 1 :(得分:1)
我遇到了同样的问题,并通过为我的套接字使用一个简单的Wrapper-Class来解决它。 该类的对象必须存在于需要读/写操作的任何位置。
public class Sender implements Closeable
{
private final Socket sock;
private final ObjectOutputStream out;
private ObjectInputStream in = null;
private final Object oLock = new Object();
private final Object iLock = new Object();
//optional
public boolean isClosed(){
return sock.isClosed();
}
//there is a better way to do this
public Socket getSocket(){
return sock;
}
//use this to send data
public void send(Object o) throws IOException {
synchronized (oLock){
getOOS().writeObject(o);
}
}
//use this to read data
public Object get() throws IOException {
synchronized (iLock){
return getOIS().readObject();
}
}
private ObjectOutputStream getOOS() {
return out;
}
//not the best way... but wouldn't work otherwise
private ObjectInputStream getOIS() throws IOException {
if(in == null)
in = new ObjectInputStream(sock.getInputStream());
return in;
}
public Sender(Socket s) throws IOException {
sock = s;
out = new ObjectOutputStream(s.getOutputStream());
//in = new ObjectInputStream(s.getInputStream());
//getting the input and output stream gave me some weird deadlock
}
//optional
@Override
public String toString() {
return sock.toString();
}
//flush and close if sock is not yet closed
@Override
public void close() throws IOException {
if(!sock.isClosed()){
if(out != null)
out.flush();
sock.close();
}
}
}
这个在客户端运行良好(Sender是连接到服务器的Socket)和 server(发件人是连接到客户端的套接字)。
希望这有帮助。
Greets roop
答案 2 :(得分:0)
服务器是在9990读取对象后关闭连接,还是失败?
完成此操作后,您可以使用快速对象序列化程序(如kryo
)查看优化速度序列化答案 3 :(得分:0)
我没有java套接字的经验,但是通过行s.setTcpNoDelay(true);我认为您的程序正在使用tcp发送数据包,请尝试使用udp。 tcp协议旨在保证数据包到达目的地,为此,它必须在到达时验证完整性。另一方面,udp没有这样做,它只发送数据包而不关心完整性,这就是在线多人游戏使用它的原因。