请教如何判断SOCKET长连接通信中,一段时间内是否收到对方的信息.及相关问题.
对方的接口文档中要求:
1.2 业务接口
服务端地址:211.151.234.131 端口号:9007
Tcp协议适合发送量大,发送和接收比较及时,对于Tcp客户端由于某些原因一段时间内不能连接到分发中心服务器,所有的发向该客户端的MO短信和报告都会被缓存起来,等该客户端一旦连接,便会很快补发。
建议合作方建立一个发送一个接收2个连接,如果业务量很大,可以申请多于2个的连接,但须向业务申请后方可加连接,系统对于连接数是有限制的,每个合作方没有特殊声明时连接数是3,一般可以建2个连接,一个连接用于缓冲在某些情况下断开不能很好识别的情况。还有,对于每条连接,我们目前的速度限制是10条/秒,如果你的业务超过每连接每秒10条的限制,可以向业务申请调高每条连接的最高限速。
服务器端要求每连接每分钟都要能从客户端接收到至少一条指令数据,如果超过一分钟没有收到,服务器会向客户端发送一个测试指令,只要合作方回应该指令,那么就认为连接是处于激活状态,如果3分钟内服务端都无法接收到客户端的测试回应,将主动断开连接。客户端程序也应该设置3分钟内不能收到服务器端任何指令将主动断开连接并重新连接。为了防止分发中心连接负载太重,我们要求任何一个连接因任何原因在断开后20秒内不得连接,20秒后再尝试连接,否则如果在1分钟内超过我们设定的连接次数,我们将限制其在后续10分钟之内不能连接,并向系统管理员告警,由系统管理员根据情况停止该用户的合作帐户。
1.2.1 连接登陆指令
连接登陆指令是在客户端成功连接后首先应当而且只能在此时发送的指令:
格式:
Login Name=【注册名】&Pwd=【注册密码】&Type=【注册类型,0:接收和发送;1:接收;2:发送;默认为0】(回车换行)
如果所有服务注册成功,服务器返回给客户端字符串:
Pass(回车换行)
否则将断开连接。对于一次未连接成功,应至少在20秒以后再重试连接,禁止连续的重试连接。
请问红色的话,我应该如何设置三分钟内不收到服务器任何指令将主动断开连接并重新连接.
我写的主要的客户端的代码:
父类线程:
public class ParentThread extends Thread {
private Socket socket;
protected BufferedReader reader;
protected BufferedWriter writer;
protected boolean isConnection=false;
protected boolean login(int type){
LoginRequest login = new LoginRequest(type);
//login.setRegType(type);
login.create();
try {
writer.write(login.getOrder());
writer.flush();
String str_order = reader.readLine();
System.out.println(str_order);
// PassResponse pass = new PassResponse(str_order);
// if(pass.isPass()){
if("Pass".equals(str_order)){
return true;
}else{
return false;
}
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
protected void init(){
try {
socket = new Socket(Const.distributeCenterIP,Const.distributeCenterPort);
//socket.setSoTimeout(50000);
reader =new BufferedReader(new InputStreamReader(socket.getInputStream()));
writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
isConnection=true;
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
protected void closeSocket(){
isConnection=false;
try {
if(reader != null)reader.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if(writer != null)writer.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if(socket != null)socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
接收短信连接,继承父类线程
public class SmsReceiver extends ParentThread {
private boolean toReconnection=false;
@Override
public void run() {
// TODO Auto-generated method stub
try{
init();
//登陆
boolean b = login(Const.reg_type_receive);
if(!b){//登陆失败,退出
SmsMain.log.error("登陆失败,程序退出!请检查注册名和口令是否正确";
SmsMain.log.info("注册名名:"+Const.reg_name);
SmsMain.log.info("用户口令:"+Const.reg_pwd);
SmsMain.log.info("注册类型:"+Const.reg_type_receive);
}
}catch(Exception e){
toReconnection = true;
}
while(true){
if(toReconnection){
/**20秒连接一次*/
try {
sleep(20000);
init();
//登陆
boolean b = login(Const.reg_type_receive);
toReconnection=false;
if(!b){//登陆失败,退出
SmsMain.log.error("登陆失败,程序退出!请检查注册名和口令是否正确";
SmsMain.log.info("注册名名:"+Const.reg_name);
SmsMain.log.info("用户口令:"+Const.reg_pwd);
SmsMain.log.info("注册类型:"+Const.reg_type_receive);
break;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if(!isConnection){//连接失败
toReconnection = true;
continue;
}
try {
String str_order = reader.readLine();
System.out.println(str_order);
Order order = new Order(str_order);
//如果为测试指令,发送回应
//if(order.isTestOrder()){
if("test".equals(str_order)){
System.out.println("---测试----";
writer.write(order.testOrder);
writer.flush();
toReconnection = false;
continue;
}
//处理
SMSBusinessCenter sbc = new SMSBusinessCenter(order);
Properties prop=sbc.performTask();
//发送回应
System.out.println(prop.getProperty("CommandId");
received(prop.getProperty("CommandId");
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void received(String cid){
//Received received = new Received(Utils.getCurrentCommandId());
// Received received = new Received(cid);
// received.create();
try {
writer.write("Received CommandId="+cid+"\r\n";
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
发送短信连接,继承父类线程:
public class SmsSend extends ParentThread {
private boolean toReconnection=false;
@Override
public void run() {
try{
init();
//登陆
boolean b = login(Const.reg_type_send);
if(!b){//登陆失败,退出
SmsMain.log.error("登陆失败,程序退出!请检查注册名和口令是否正确";
SmsMain.log.info("注册名名:"+Const.reg_name);
SmsMain.log.info("用户口令:"+Const.reg_pwd);
SmsMain.log.info("注册类型:"+Const.reg_type_send);
}
}catch(Exception e){
toReconnection = true;
}
while(true){
if(toReconnection){
/**20秒连接一次*/
try {
sleep(20000);
init();
//登陆
boolean b = login(Const.reg_type_send);
toReconnection=false;
if(!b){//登陆失败,退出
SmsMain.log.error("登陆失败,程序退出!请检查注册名和口令是否正确";
SmsMain.log.info("注册名名:"+Const.reg_name);
SmsMain.log.info("用户口令:"+Const.reg_pwd);
SmsMain.log.info("注册类型:"+Const.reg_type_send);
break;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if(!isConnection){//连接失败
toReconnection = true;
continue;
}
try {
String str_order = reader.readLine();
Order order = new Order(str_order);
//如果为测试指令,发送回应
if(order.isTestOrder()){
writer.write(order.testOrder);
toReconnection = false;
//continue;
}
// //处理
// SMSBusinessCenter sbc = new SMSBusinessCenter(order);
// Vector msgs = sbc.getSendMsg();
// //发送短信
// //for(){
// writer.write("";
//
//
//发送短信
if(SmsMain.list!=null&&SmsMain.list.size()>0){
synchronized (SmsMain.list) {
for (Iterator iterator = SmsMain.list.iterator(); iterator
.hasNext() {
SubmitRequest sr = (SubmitRequest) iterator.next();
StringBuffer sb = new StringBuffer();
sb.append(Const.order_submit+" ")
.append("CommandId="+sr.getCommandId())
.append("&GateWay="+sr.getGateWay())
.append("&GateName="+sr.getGateName())
.append("&ItemId="+sr.getItemId())
.append("&SpNumber="+sr.getSpNumber())
.append("&UserNumber:="+bin2hex(sr.getUserNumber()))
.append("&UserNumberType="+sr.getUserNumberType())
.append("&FeeNumber="+sr.getFeeNumber())
.append("&FeeNumberType="+sr.getFeeNumberType())
.append("&FeeType="+sr.getFeeType())
.append("&ScheduleTime="+sr.getScheduleTime())
.append("&ExpireTime="+sr.getExpireTime())
.append("&MtFlag="+sr.getMtFlag())
.append("&ReportFlag="+sr.getReportFlag())
.append("&MsgCode="+sr.getMsgCode())
.append("&MsgId="+sr.getMsgId())
.append("&ExtData:="+sr.getExtData())
.append("&TP_pId="+sr.getTp_pId())
.append("&TP_udhi="+sr.getTp_udhi())
.append("&Msg:="+bin2hex(sr.getMsg()))
.append("&LinkID="+sr.getLinkID())
.append("&ItemType="+sr.getItemType()+"\r\n");
writer.write(sb.toString());
writer.flush();
SmsMain.list.remove(sr);
}
}
//接受回应
received();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void received(){
try {
String line = reader.readLine();
// Received received = new Received(line);
// received.parse();
System.out.println(line);
SmsMain.log.info(line);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 字符串转换成十六进制值
* @param bin String 转换成十六进制的字符串
* @return
*/
public static String bin2hex(String bin) {
char[] digital = "0123456789ABCDEF".toCharArray();
StringBuffer sb = new StringBuffer("");
byte[] bs = bin.getBytes();
int bit;
for (int i = 0; i < bs.length; i++) {
bit = (bs & 0x0f0) >> 4;
sb.append(digital[bit]);
bit = bs & 0x0f;
sb.append(digital[bit]);
}
return sb.toString();
}
}
----------------------------------------------------------
语言:C#
问题:在socket通信时,怎么样判断socket双方是否断开连接
我在Server端new了一个socket,然后bind,开了一个线程来accept前来连接的client,每接到一个client前来连接就新开一个线程和它进行通信。
我把Server端得到的socket放到一个集合里,我想知道集合里的socket是否断开连接,如果断开连接我就把它从这个集合里移除。
判断socket是否断开连接,网上有N种说法:
1.Socket.Connected
这个属性只能说明上一次通信时还是正常的。
2.Socket.Pool
这个方法是可以,但是它要从socket里读或写部分数据,如果其他线程从这个socket读写数据,那么数据将会出错。我在写一个远程通信软件时候就出现这个问题了。
而且http://technet.microsoft.com/zh-cn/system.net.sockets.socket.poll.aspx上这样说的:
此方法不能检测某些类型的连接问题,例如,网络电缆中断或远程主机意外关闭。您必须尝试发送或接收数据以检测这些类型的错误。
3.使用心跳包
每隔一段时间,socket一方向另一方发送一段特殊的数据,socket的另一方接到这个数据后回发回来。这样就能判断socket两方都没有掉线了。
请问:还没有解决方案有快速准确判断socket双方是否断开连接?
如果您有解决方法,请不吝赐教,十分感谢。
如果您不能解决此问题,请不要回复,谢谢合作。