c 与java通信_javaSocket与C通信

前段时间写了个web端与C服务端之间的通信不过用的是短连接 非堵塞的方式,一直想使用长连接,使tomcat启动的时候就和C服务端进行通信,但是一直没找到方法希望je的朋友能给点思路。先来看我现在的具体实现

通信的核心类

public

class

newsSockBase

{

private

SocketChannel sc;

private

final

int

MAX_LENGTH =

8192

;

private

ByteBuffer r_buff ;

private

ByteBuffer w_buff ;

private

static

String host ;

private

static

int

port;

int

sendBufTotalLen;

int

sendBufLen;

int

sendBufStart;

byte

[]  sendBuf;

int

recvBufTotalLen;

int

recvBufLen;

int

recvBufStart;

byte

[]  recvBuf;

int

timeout;

String  msg;

public

newsSockBase()

{

r_buff = ByteBuffer.allocate(MAX_LENGTH);

w_buff = ByteBuffer.allocate(MAX_LENGTH);

sendBufTotalLen = MAX_LENGTH;

sendBufLen = sendBufStart =

0

;

sendBuf =

new

byte

[MAX_LENGTH];

recvBufTotalLen = MAX_LENGTH;

recvBufLen = recvBufStart =

0

;

recvBuf =

new

byte

[MAX_LENGTH];

timeout =

6

;

}

public

void

setIPandPort(String str,

int

pt)

{

host = str;

port  = pt;

}

//这两个函数一定要注意 形参是基类 而实际传入的参数是子类,到时候也是调用子类的参数来做

public

void

getBufFrompara(InewsDetail nD)

{

int

len = nD.encode(sendBuf, sendBufStart, sendBufTotalLen-sendBufStart-sendBufLen);

sendBufLen += len;

}

public

int

decodeBufToPara(InewsDetail nD)

{

int

len = nD.decode(recvBuf, recvBufStart, recvBufLen);

if

(len>

0

)

//解码正确的时候才做

{

recvBufLen -= len;

recvBufStart += len;

}

return

len;

}

public

void

start(InewsDetail nD)

{

//这里需要先根据传入的参数来

getBufFrompara(nD);

try

{

InetSocketAddress addr =

new

InetSocketAddress(host, port);

// 生成一个socketchannel

sc = SocketChannel.open();

sc.configureBlocking(

false

);

//

// 连接到server

sc.connect(addr);

while

(!sc.finishConnect())

;

System.out.println(

"connection has been established!…"

);

// while (true)

{

// 回射消息    // 复位,清空

w_buff.clear();

w_buff.put(sendBuf,sendBufStart,sendBufLen);

w_buff.flip();

// 转到最开始

// 发送消息

while

(w_buff.hasRemaining())

sc.write(w_buff);

w_buff.clear();

// 进入接收状态

while

(

true

)

{

int

ss=

0

;

int

count;

r_buff.clear();

while

(ss

100

)

{

count = sc.read(r_buff);

if

(count>

0

)

break

;

ss++;

Thread.currentThread().sleep(

10

);

}

if

(ss==timeout)

{

break

;

}

r_buff.flip();

//判断recvBuf能不能放下接收到的数据

if

(r_buff.limit()+recvBufStart+recvBufLen>recvBufTotalLen)

{

//放不下了

//那就先看看前面是不是有空余

if

(recvBufStart>

0

)

{

for

(

int

i=

0

;i

{

recvBuf

= recvBuf[i+recvBufStart];

}

recvBufStart = 0;

}

if (r_buff.limit()+recvBufStart+recvBufLen>recvBufTotalLen)

{

//这个时候就是真的说数据区长度不够了,属于致命错误

System.err.println("致命错误! 缓冲区长度过小!");

}

}

else

{   // 也可以转化为字符串,不过需要借助第三个变量了。

r_buff.get(recvBuf,recvBufStart+recvBufLen,r_buff.limit());

//得到了一次数据就要试着做一次解码,如果能够解码,那就完成解码,不能则表示数据不完整,继续等待新数据

//这里注意返回值 如果是0  表示数据不完整 如果是正数 就是解码的字节数 负数表示解码出错

recvBufLen += r_buff.limit();

if (decodeBufToPara(nD)!=0)

break;

}

System.out.println("reply is " + r_buff.limit() + " long " );

}

}

sc.socket().close();

} catch (IOException ioe) {

ioe.printStackTrace();

} catch (InterruptedException ie) {

ie.printStackTrace();

}

System.out.println("Exit App....... " );

}

public static void main(String[] args)

{

newsDetailNewsSum nDNS = new newsDetailNewsSum();

newsSockBase nsb = new newsSockBase();

nsb.setIPandPort("192.168.0.106",8888);

nsb.start(nDNS);

System.out.println("Exit Allllll....... " );

}

}

下面是报文协议的基类

//此类试图将所有的通讯协议的编解码都包含在内!按照一次交互的过程来区分

public class newsDetail implements InewsDetail

{

protected int       netErr; //用来表示是不是网络出错了,主要是超时。这个时候就不需要检查其他参数了。

protected int       type;   //就是对应具体的操作类型码

protected byte[]    StreamID=new byte[16];  //对应具体的流水号

protected byte[]    asyn = new byte[2];

//这个还是有问题 不能达到预计效果 需要修改

static private int  seq=0;  //生成流水号后2位的时候使用的

static private Calendar lastCa;

public newsDetail()

{

getStreamID();

}

public int getType() {

return type;

}

public void setType(int type) {

this.type = type;

}

//基类中的编解码函数没有作用,具体使用的编解码函数在各个子类中需要重新实现

//必须有返回值 因为调用者需要根据返回值做一些操作

//这里的参数 buf是需要填写的缓冲区  start 是缓冲区开始位置 len 是可用的缓冲区长度

public int encode(byte[] buf,int start,int len)

{

return 0;

}

//这里的参数 buf是需要需要解码的缓冲区  start 是缓冲区开始位置 len 是需要解码的长度

public int decode(byte[] buf,int start,int len)

{

return 0;

}

public void getStreamID()

{

Calendar ca = Calendar.getInstance();

int year = ca.get(Calendar.YEAR);//获取年份

int month=ca.get(Calendar.MONTH)+1;//获取月份

int day=ca.get(Calendar.DATE);//获取日

int minute=ca.get(Calendar.MINUTE);//分

int hour=ca.get(Calendar.HOUR);//小时

int second=ca.get(Calendar.SECOND);//秒

int am_pm=ca.get(Calendar.AM_PM);

if (am_pm==Calendar.PM)

hour += 12;

if (hour>=24)

hour -= 24;

System.out.println(seq);

if (lastCa!=ca)

{

lastCa = ca;

seq = 12;

}

else

{

seq++;

if (seq>=100)

seq = 0;

}

//现在根据上面的字段组成StreamID字符串

//目前先使用手工的办法来写,效率高一些

StreamID[0] = (byte)(year/1000+'0');

StreamID[1] = (byte)((year-(StreamID[0]-'0')*1000)/100+'0');

StreamID[2] = (byte)((year-(StreamID[0]-'0')*1000-(StreamID[1]-'0')*100)/10+'0');

StreamID[3] = (byte)(year-(StreamID[0]-'0')*1000-(StreamID[1]-'0')*100-(StreamID[2]-'0')*10+'0');

StreamID[4] = (byte)(month/10+'0');

StreamID[5] = (byte)((month-(StreamID[4]-'0')*10)+'0');

StreamID[6] = (byte)(day/10+'0');

StreamID[7] = (byte)((day-(StreamID[6]-'0')*10)+'0');

StreamID[8] = (byte)(hour/10+'0');

StreamID[9] = (byte)((hour-(StreamID[8]-'0')*10)+'0');

StreamID[10] = (byte)(minute/10+'0');

StreamID[11] = (byte)((minute-(StreamID[10]-'0')*10)+'0');

StreamID[12] = (byte)(second/10+'0');

StreamID[13] = (byte)((second-(StreamID[12]-'0')*10)+'0');

StreamID[14] = (byte)(seq/10+'0');

StreamID[15] = (byte)((seq-(StreamID[14]-'0')*10)+'0');

System.out.println("现在时间");

System.out.println("用Calendar.getInstance().getTime()方式显示时间: " + ca.getTime());

System.out.println("用Calendar获得日期是:" + year +"年"+ month +"月"+ day + "日");

System.out.println("用Calendar获得时间是:" + hour +"时"+ minute +"分"+ second +"秒");

}

public static void main(String[] args)

{

{

newsDetail nn1 = new newsDetail();

}

try {

Thread.currentThread().sleep(3000);

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值