67,513
社区成员
发帖
与我相关
我的任务
分享
Socket socket=null;
try {
//在客户端建立一个Socket对象,请求建立连接:
socket=new Socket("125.208.3.12",11084);
//输出
System.out.println("连接已建立:"+socket);
OutputStream os=socket.getOutputStream();
InputStream in=socket.getInputStream();
//发送登录
os.write(login.getBytes());
os.flush();
Thread.sleep(3000);
//发送信息01
os.write(sendmes.getBytes());
os.flush();
Thread.sleep(3000);
//发送信息02
os.write(sendmes1.getBytes());
os.flush();
int c;
while((c=in.read())!=-1)
{
System.out.print((char)c);
}
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
[quote=引用 28 楼 oh_Maxy 的回复:] 你的那个while(true)会无间断的读取数据,加入list,感觉这里使用wait也是可以的。如果wait和sleep都没有,这样操作下去可能会有问题。 另外,你的这段代码应该不是真实使用的代码吧? 还有,建议byte[] b这个声明放到循环体外面,这样就不会每次执行都重新声明一个引用b了。
心跳报文,应该是标记比较特别的一个报文了,可以给个响应给服务端,告诉它我收到心跳了。
你的那个while(true)会无间断的读取数据,加入list,感觉这里使用wait也是可以的。如果wait和sleep都没有,这样操作下去可能会有问题。 另外,你的这段代码应该不是真实使用的代码吧? 还有,建议byte[] b这个声明放到循环体外面,这样就不会每次执行都重新声明一个引用b了。
另外,wait方法,没怎么用过,如果是测试方法,可以使用,项目里还是慎用吧。 (main方法里的sleep的原因是,你的线程start之后,是异步的了,需要一段时间才能执行完,所以要sleep才有结果)
public class test3 {
//读取服务端返回的报文存放的集合
public static LinkedList reportLink=new LinkedList();
//解析后的报文存放在此处
public static LinkedList<MessageEntity> resultList=new LinkedList<MessageEntity>();
//解析后将登录返回的报文存到此队列
public static LinkedList<MessageEntity> loginreportLink=new LinkedList<MessageEntity>();
//将解析后的心跳报文存到此队列
public static LinkedList<MessageEntity> echoreportLink=new LinkedList<MessageEntity>();
}
这个是俩个方法分别是从队列获取值和向队列添值写的方法,等待和唤醒线程就是通过这执行的!
public synchronized void addMessage(String message)
{
reportLink.add(message);
this.notifyAll();
}
public synchronized String getMessage() throws InterruptedException
{
while(reportLink.isEmpty())
{
wait();
}
// System.out.println("输出"+reportLink.removeFirst());
return (String) reportLink.removeFirst();
}
另外请教一个问题:
这个代码是我使用死循环读取服务端给我返回数据方法,这个方法是放在一个线程里的执行的!
现在想问的是,上次我请教一个人,他说让我把线程休眠一下,说是为了防止死循环造成CPU使用过高,导致电脑瘫痪!我得理解是既然我读取服务端的数据是一个堵塞的方法,这个休眠写不写还有意思吗?
while(true)
{
//读取数据
byte[]b=new byte[150];
//存入集合
linkedlist.add(new String (b));
//此处要让这个循环休眠一下,不知道这样写的用意是什么?
Thread.sleep(2);
}
另外,wait方法,没怎么用过,如果是测试方法,可以使用,项目里还是慎用吧。 (main方法里的sleep的原因是,你的线程start之后,是异步的了,需要一段时间才能执行完,所以要sleep才有结果)
另外,wait方法,没怎么用过,如果是测试方法,可以使用,项目里还是慎用吧。 (main方法里的sleep的原因是,你的线程start之后,是异步的了,需要一段时间才能执行完,所以要sleep才有结果)
public class readThread implements Runnable{
//线程
public void run()
{
readwork();
}
//接受完整报文的队列
public final static LinkedList ReciveMessage=new LinkedList();
//解析存入的集合
List<MessageEntity> list=new ArrayList<MessageEntity>();
//向队列添值
public void addReciveMessage(String message)
{
synchronized(ReciveMessage)
{
ReciveMessage.add(message);
this.notifyAll();
}
}
//获取队列的值
//获取队列的第一个值
public Object getReciveMessage() throws InterruptedException
{
while(ReciveMessage.isEmpty())
{
wait();
}
synchronized (ReciveMessage)
{
return ReciveMessage.removeFirst();
}
}
//读取服务端返回的数据并调用解析的方法将解析的数据存储到集合中()
public void readwork()
{
while(true)
{
//上面的代码
//向队列添加数据(读取到的完整报文)
addReciveMessage(message);
//调用解析报文的方法添加到list集合
jiexi(getReciveMessage());
}
}
//解析的fangfa
public void jiexi(String message)
{
//实体类
MessageEntity me=new MessageEntity();
//将解析后的数据存入到list集合
list.add(me);
}
}
另外一个需求,可以考虑使用Observer接口和Observable类,实现观察者:当线程对list进行add操作时,触发下观察者。LZ可以搜下观察者实现案例,不难的。心跳报文,应该是标记比较特别的一个报文了,可以给个响应给服务端,告诉它我收到心跳了。
public class readThread implements Runnable{
//线程
public void run()
{
readwork();
}
//接受完整报文的队列
private final LinkedList ReciveMessage=new LinkedList();
//解析存入的集合
List<MessageEntity> list=new ArrayList<MessageEntity>();
//向队列添值
public void addReciveMessage(String message)
{
synchronized(this)
{
ReciveMessage.add(message);
this.notifyAll();
}
}
//获取队列的值
//获取队列的第一个值
public synchronized Object getReciveMessage() throws InterruptedException
{
while(ReciveMessage.isEmpty())
{
wait();
}
return ReciveMessage.removeFirst();
}
//读取服务端返回的数据并调用解析的方法将解析的数据存储到集合中()
public synchronized void readwork()
{
while(true)
{
//上面的代码
//向队列添加数据(读取到的完整报文)
addReciveMessage(message);
//调用解析报文的方法添加到list集合
jiexi(getReciveMessage());
}
}
//解析的fangfa
public void jiexi(String message)
{
//实体类
MessageEntity me=new MessageEntity();
//将解析后的数据存入到list集合
list.add(me);
}
os.write(login.getBytes());
os.flush();
os.write(echo.getBytes());
os.flush();
os.write(echo.getBytes());
os.flush();
os.write(echo.getBytes());
os.flush();
readThread r=new readThread(in);
Thread t=new Thread(r);
t.start();
//加入这句,可以再list集合里读到数据
Thread.sleep(3000);
for (int i = 0; i < r.list.size(); i++) {
System.out.println("返回状态:"+r.list.get(i).getBrespCode());
}
你好,帮我看下这个问题!上面的代码是我写了一个readThread的线程,步骤是:读取完整的报文>>将完整的报文先存到队列中>>从队列中获取一条报文解析并将解析到的数据存到list集合中!
现在的问题是,我在main方法里测试的时候(下边的代码)我直接输出read线程的list集合是获取不到数据的!我在线程开始时加入了一句sleep就可以读到线程的数据了!我上面写的几个方法,(向队列加值,从队列取值,读取队列的值,解析队列的值)都加了一个synchronized,这是我参考的别的代码加上的,是让线程同步的!现在有个疑问,我现在就仅仅使用了一个线程,我现在加不加synchronized都可以是吧,还有现在在向队列添值和取值的时候是不是写的那个wait()和this.notifyAll();是不是没用呢!但是基于刚才那个在main方法里加入sleep这句才可以取到解析后返回的值!现在我想这样弄就是:再开一个线程,要让他能够及时的输出list集合里的值,而不用在main方法里sleep几秒。也就是说我要让这个线程可以在有数据的时候,就this.notifyAll()唤醒他,没有数据的时候就wait(),等待他输入数据后就在此this.notifyAll()唤醒他,要怎么写呢?给我说下思路也可以!下午我自己写了一个线程,可是还是没写对!顺便先帮我参考下上面的代码,我要怎么改下。我感觉现在这得代码有问题,但不知道哪的问题,怎么改..谢谢了![quote=引用 16 楼 oh_Maxy 的回复:] 不清楚你们的系统能不能保证先后顺序。如果能保证FIFO,你的方式是可以的。如果会有先后顺序不一情况的话,按长度就很有风险了。
你的代码“读取报文长度”,mlen这样处理的话,只能是个位数的长度了对吧?建议长度直接转换为byte存储,解析的时候也直接读取即可:int len=bmesgLen;这样长度最大可达0~127。 //读取本条报文剩余的数据 byte[]result=new byte[len-10]; 这一步为啥要减10,不太理解。其它没啥建议了。
不清楚你们的系统能不能保证先后顺序。如果能保证FIFO,你的方式是可以的。如果会有先后顺序不一情况的话,按长度就很有风险了。
你的代码“读取报文长度”,mlen这样处理的话,只能是个位数的长度了对吧?建议长度直接转换为byte存储,解析的时候也直接读取即可:int len=bmesgLen;这样长度最大可达0~127。 //读取本条报文剩余的数据 byte[]result=new byte[len-10]; 这一步为啥要减10,不太理解。其它没啥建议了。
心跳报文,应该是标记比较特别的一个报文了,可以给个响应给服务端,告诉它我收到心跳了。
放finally或while后面都可以的。试试呗~
[quote=引用 11 楼 n_e_e_d 的回复:] [quote=引用 6 楼 oh_Maxy 的回复:] 放finally或while后面都可以的。试试呗~
//读取块标识
byte[] bblockMark=new byte[3];
in.read(bblockMark);
String blockMark=new String(bblockMark);
//读取版本识别码
byte[] bverID=new byte[1];
in.read(bverID);
String verid=new String(bverID);
//读取报文长度
byte[] bmesgLen=new byte[6];
in.read(bmesgLen);
String mlen=new String(bmesgLen);
int len=Integer.parseInt(mlen);
//读取本条报文剩余的数据
byte[]result=new byte[len-10];
in.read(result);
String th=new String(result);
//返回整条的完整报文
String message=blockMark+verid+mlen+th;
System.out.println(message);
[quote=引用 6 楼 oh_Maxy 的回复:] 放finally或while后面都可以的。试试呗~