我遇到流数据捕获中的一个问题,即在多线程读取广播数据时,请帮助或建议,
实际上有一个类正在从一个udp套接字读取数据。另一个类接受来自每个客户端请求的tcp连接,为每个客户端创建一个线程,并为数据请求相同的udp类。事情正在与创建的第一个线程一起工作。但是当我从另一个pc / ip请求另一个客户端时,数据包会丢失到第二个客户端/线程
我通过创建一个存储Threads输出流对象的列表来解决方法 并循环它以将数据发送到所有客户端。但这只是暂时的,因为如果客户端/连接增加,它会延迟数据包。
用于读取UDP数据的代码
public class EventNotifier
{
private InterestingEvent ie;
public DatagramSocket clientSocket;
public String[] split_str;
byte[] receiveData;
HashMap<String, String> secMap = new HashMap<String, String>();
public EventNotifier(InterestingEvent event)
{
ie = event;
clientSocket = new DatagramSocket(9050);
receiveData = new byte[500];
}
public String getDataFeed(String client_id)
{
try
{
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
clientSocket.receive(receivePacket);
String s = new String(receivePacket.getData());
String split_str = s.split(",");
if(secMap.containsValue(split_str[0]))
return s;
else
return "";
} catch(Exception e3) {}
}
}// end of eventNotifier class
用于处理客户端请求的多线程的代码
public class multiServer
{
static protected List<PrintWriter> writers = new ArrayList<PrintWriter>();
static String client_id = "";
public static void main(String[] args)
{
try
{
ServerSocket servsock = new ServerSocket(8858);
Socket incoming;
while(true)
{
incoming = servsock.accept();
multiServerThread connection = new multiServerThread(incoming);
Thread t1 = new Thread(connection);
t1.start();
}
}
catch(IOException e)
{
System.out.println("couldnt make socket");
}
}
}
class multiServerThread extends Thread implements InterestingEvent
{
Socket incoming;
PrintWriter out=null;
PrintWriter broad=null;
BufferedReader in = null;
String cliString=null;
private EventNotifier en;
int id;
public static String udp_data;
public void interestingEvent(String str1)
{
this.udp_data = str1;
}
public String getUdpData()
{
String _udp_data = this.udp_data;
return _udp_data;
}
multiServerThread(Socket incoming)
{
this.incoming=incoming;
en = new EventNotifier(this);
}
public void run()
{
try
{
out = new PrintWriter(incoming.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(incoming.getInputStream()));
cliString = in.readLine();
multiServer.writers.add(out);
while(true)
{
try
{
udp_data = en.getDataFeed(cliString);
if(udp_data!=null && udp_data.length()>0)
{
//workaround for serving the data to all cleints who are connected
for (int i=0; i<multiServer.writers.size();i++)
{
broad=multiServer.writers.get(i);
broad.println(udp_data.trim());
}
//else will directly write to the outputstream object for every thread which is connected
// out.println(udp_data.trim());
}
}
catch (Exception e)
{
System.out.println("exception "+e);
}
Thread.sleep(1);
}
} catch(IOException e)
{
System.out.print("IO Exception :: "+ e);
}
catch(InterruptedException e)
{
System.out.print("exception "+ e);
}
}
}
答案 0 :(得分:0)
您需要互斥(或不同的设计)。
例如,如果两个线程同时调用multiServer.writers.add(out);
会发生什么?
来自ArrayList Javadocs
请注意,此实现未同步。如果多个线程同时访问ArrayList实例,并且至少有一个线程在结构上修改了列表,则必须在外部进行同步。 (结构修改是添加或删除一个或多个元素的任何操作,或[...]
另一个问题是两个同时调用udp_data = en.getDataFeed(cliString);
。第二个线程可能会覆盖第一个线程的结果。你会丢失数据!
如果一个线程在另一个线程忙于执行for (int i=0; i<multiServer.writers.size();i++)
时调用multiServer.writers.add(out);
会发生什么?在out
实际添加到列表之前,大小可能已经增加了!
public class multiServer
{
private List<PrintWriter> writers = new ArrayList<PrintWriter>();
public synchronized void addWriter(PrintWrite out) {
writers.add(out);
}
public synchronized void serveAllWriters(String data) {
for (int i=0; i<multiServer.writers.size();i++)
{
broad=multiServer.writers.get(i);
broad.println(data);
}
}
}
现在,当一个线程试图添加一个编写器时,synchronized
将确保没有其他线程add
或打印。因此,应修复multiServerThread
以使用新方法:
class multiServerThread extends Thread implements InterestingEvent
{
//...
private String udp_data;
//...
myMultiServer.addWriter(out);
//...
udp_data = en.getDataFeed(cliString);
if(udp_data!=null && udp_data.length()>0)
myMultiServer.serveAllWriters(udp_data.trim());
//...
}
可能存在更多问题,不确定我是否完全理解您的代码。您必须问自己的问题是,另一个线程可以读取和/或写入相同的数据或对象吗?是?然后你需要适当的同步。