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();
}
调用这些代码可以实现给手机发送短信的功能,我现在是客户端,我给服务端发送数据后,手机号可以接收到我发送的信息。在我发送了第一条信息后,手机可以收到短息,但是执行第二条发送信息的时候,手机就是收不到信息了!客户端也只能收到登录和第一条短信发送的返回信息,请问下这个是什么原因呢?
另外他这个还有一个心跳报文,我要是连续发送俩次心跳报文的时候就都可以收到返回的信息!会不会是他们服务端的问题呢?还是我代码的问题呢?socket通信
解决方案 »
- struts2 提交出现错误 无法再次提交
- jsp页面上div被覆盖问题?
- (高手救命啊!)正则表达式 提取html中IMg
- javax.servlet.UnavailableException: Parsing error processing resource path /WEB-INF/struts-config.xml
- hibernate更新问题!!!
- 神州数码(深圳)公司面试归来
- 七 一100大相送 java 怎样登陆网站(该网站是采用session验证)并且实现页面跳转取出登陆后的一些数据(类似有些登陆软件))
- 郁闷,我安装了j2sdkee1.4.1,刚开始可以启动,我在命令行键入j2ee -verbose时提示error:org/apache/commons/launcher/LaunchFilter
- JMS求教,只有20分了。
- 再提!!!!!!解决马上给分!!一个DOM解析XML的程序jcreator里运行没事,可是引入到JSP里,在weblogic里运行报错,需要配置weblogic
- jsp中怎样得到该值??
- 很奇葩的问题,严重困扰
(嘿,LZ好纠结呀~)
服务端在人家那边,并且别人客户端有做成功的,感觉还是我代码的问题,但是现在不知道是哪的问题了!
我现在只是在一个main方法里测试的!不知道是不是这得问题呢?但是我看他的文档里说的是登陆成功以后可以发送任何形式的报文给服务端,但是我连续发送俩条短信报文以后还是只能收到第一条!第二条这老是不行
可不可以做个标记,比如以某个特殊字符或节点开头、结尾,表示一个包,这样来区分呢?
我现在的代码是这样的:先读取到他的长度,再根据长度把该条报文剩余的数据读取出来,最后再把这条报文拼接起来!
因为我要循环读取,就是现在这些代码要放到一个while循环里,不断的读取服务端返回的数据
每当读到一条完整的报文是就存储到队列里!(要让他只要有数据就一直读取呢,存储呢!)
正在思考要怎么把读到的这些报文存起来呢!还有while的条件不知道改怎么填,是写true呢,还是别的呢!总感觉有些东西不太确定!怕写了半天出错了!
下午看了会多线程,写了一个简单的多线程循环向队列存值,取值的示例!
先帮我参考下下面这样写可以吗?//读取块标识
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);
//读取本条报文剩余的数据
byte[]result=new byte[len-10];
这一步为啥要减10,不太理解。其它没啥建议了。
目前我是这样想得:先把这些信息存储起来,然后再一条条的判断哪个成功,哪个失败!这样对于我接收到的先后顺序应该就不用考虑了吧!因为我是按长度接收的,所以每条报文都应该是完整的吧?我接收到哪条的返回信息就判断哪条的返回信息!
但是这样的话,我的心跳报文发送以后要接收得话要怎么弄呢?难道在队列里取值判断以后如果是心跳报文的应答报文再返还给这?
因为他的长度占的是6个字节的位置,我使用byte数组读到后,先把这个字节数组转为字符串是为了取得他的长度,假如我的长度为000150的话,我转成String后显示的是000150,我再转下int就是150了,即这条报文的长度。len-10,len代表的是这条报文的长度,-10是因为我在缓冲区已经读取了10个字节流了,所以我只能读取这条报文在缓冲区的剩余的150-10个字节流了!
目前我是这样想得:先把这些信息存储起来,然后再一条条的判断哪个成功,哪个失败!这样对于我接收到的先后顺序应该就不用考虑了吧!因为我是按长度接收的,所以每条报文都应该是完整的吧?我接收到哪条的返回信息就判断哪条的返回信息!
但是这样的话,我的心跳报文发送以后要接收得话要怎么弄呢?难道在队列里取值判断以后如果是心跳报文的应答报文再返还给这?
因为他的长度占的是6个字节的位置,我使用byte数组读到后,先把这个字节数组转为字符串是为了取得他的长度,假如我的长度为000150的话,我转成String后显示的是000150,我再转下int就是150了,即这条报文的长度。len-10,len代表的是这条报文的长度,-10是因为我在缓冲区已经读取了10个字节流了,所以我只能读取这条报文在缓冲区的剩余的150-10个字节流了!
嗯,你的这种读取思路很好啊,赞一个~
建议blockMark、bverID还是要判断下,合法值才继续往下读。
其它的,没实际用过,也不好建议啦~
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()唤醒他,要怎么写呢?给我说下思路也可以!下午我自己写了一个线程,可是还是没写对!顺便先帮我参考下上面的代码,我要怎么改下。我感觉现在这得代码有问题,但不知道哪的问题,怎么改..谢谢了!
//线程
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可以搜下观察者实现案例,不难的。
--你不是想公用一个队列来处理的么?当然要操作同一个list了。如果我理解错了的话,那你把static去掉好了。假如我在这儿写完以后,在另一个线程里要调用这个线程是不是这些方法就得加锁了呢?就是另一个线程要调用这个线程,这个线程要调用这些方法!
--方法加不加锁,要看情况。比如你的这个类,如果new了多个线程对象,就算方法(非静态方法)加锁了,也只是锁住new的对象那块的方法。还有我上次看到一个单态模式(应该是一个类只能实例化一次了吧?),因为多线程的情况下会实例化多次,这样会有什么隐患吗?使用单态模式是为了避免什么呢?
--单例一般是某个接口功能,或者工具类,对外呈现的时候,要保持单一性,避免互斥操作以及减少内存消耗。使用多线程,十有八九是为了互斥操作,应该会new多次的,不要使用单例。还有,我最后是要写一个Servlet接口,然后在接口里面传值,将信息发送出去的,是不是现在在main方法里测试不合适呢!或者是我还没写后面的发送线程,这个传值也要使用到线程和队列吧?我要在保持socket连接的时候通过队列来向线程里面传值,使他可以在socket连接的时候,从队列中获取值然后发送!就是队列有值就让线程去发送,没值就等待?
--main里测试可以的,servlet实现的时候,也可以使用sleep的,虽然不是很好。不过话说回来,一个servlet请求,就没必要使用多线程来测试了,直接串行操作,没问题的。
--sock本身可以多线程,但是针对每一个socket,似乎发一条消息,就会等待了的,不需要人为操作去等的吧?
在while循环里读取到数据的时候,我是使用了线程里的wait()和this.notifyAll(),来控制线程的!当有数据的时候就唤醒线程,没数据的时候就等待了!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);
}
还有,建议byte[] b这个声明放到循环体外面,这样就不会每次执行都重新声明一个引用b了。
看不出来有啥问题。
编码规范中,要求将对象的声明放到循环体外。否则每次循环都要重新声明一个引用,占用栈空间。