关于socket的问题···求大神!谢谢

cdkx945 2012-07-01 03:34:57
我现在已经写好了一个服务端的socket 主要完成的功能是当客户端发出登陆请求等请求的时候 予以响应 也就是当接收到客户端的数据包时,被动的发回响应数据包
那么, 现在我应该如何写,才能通过调用指定的方法来发送指定数据包呢?
...全文
209 10 打赏 收藏 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
cdkx945 2012-07-03
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 的回复:]

楼主C语言出身的 ?
没有根据交互过程进行类的封装啊。

这个协议本身我都没弄明白,更别说CCID了。


至于楼主的问题,根据经验,当客户端连接到服务端之后,客户端发送特定的数据包给服务端,里面含有CCID,
服务端接收该数据包后,解析数据包,得到CCID,就OK了。
[/Quote]
我又定义了一个private HashMap<String,Ecc> eccHashMap = new HashMap<String,Ecc>();
然后写了一个
    public void sendMessage(byte ccid){
Ecc ecc=eccHashMap.get(ccid);
byte sendOpenLight[] = new byte[]{(byte)0x4c,0x53,ccid};
ecc.write(sendOpenLight);
}



如果我现在想测试一下这个代码,用一个软件模拟客户端发送数据包上来,然后用HashMap存入连接进来的客户端,然后我用那个sendMessage的方法获得客户端登陆连接进来的ccid,并且写入指定的数据包,在上面的这个方法中,我随意定义了一个数据包。作为测试··· 那么我写测试类 应该如何写呢?
冰思雨 2012-07-02
  • 打赏
  • 举报
回复
楼主C语言出身的 ?
没有根据交互过程进行类的封装啊。

这个协议本身我都没弄明白,更别说CCID了。


至于楼主的问题,根据经验,当客户端连接到服务端之后,客户端发送特定的数据包给服务端,里面含有CCID,
服务端接收该数据包后,解析数据包,得到CCID,就OK了。
cdkx945 2012-07-02
  • 打赏
  • 举报
回复
                                                       break;
case 0x20:
//查询数据回应 ,处理并存入数据库
if (login_succed==true) {
switch (packet_cmd_reserved) {
case 0x00://正常响应
System.out.println("recive_valid_length is "+ recive_valid_length);
byte send_meter [] = new byte [recive_valid_length];
for (int i = 0; i < send_meter.length; i++) {
send_meter[i] = reciver_buffer[i+8];
}
boolean crc_check = ModbusCrc16.checkBuf(send_meter);
System.out.println("crc check is "+crc_check);
if (crc_check) {
MeterDatas meter = new MeterDatas(send_meter, ccid);
if (meter.MeterUpdate()) {
//存到数据库或者直接传给需要客户端
System.out.println("DIO is :"+(0xff & meter.DIO));
System.out.println("Ua is :"+meter.Ua);
System.out.println("Ub is :"+meter.Ub);
System.out.println("Uc is :"+meter.Uc);
System.out.println("HZ is :"+meter.Hz);
}
else {
System.out.println("meter datas parse error!");
}
}
break;
case 0x01://异常响应
System.out.println("read meter error!");
break;
default:
break;
}
}

break;
case 0xd0:
String eccidString = Integer.toString(((0xff & reciver_buffer[8])<<8)+(0xff & reciver_buffer[9]));
System.out.println("eccid is "+ eccidString);
sendSocket=socketHashMap.get(eccidString);
if (sendSocket!=null) {
OutputStream sop = sendSocket.getOutputStream();
System.out.println("sendSocket is exsitl!");
valid_data_length = 0x0b;
byte sum1=0;
byte meterAddr =(byte) (0xff & reciver_buffer[10]);
byte meterCmd = (byte)0x10;
int regStartAddr =0x21;
int regCount = 0x01;
int crcValue=0x00;
int eccid =Integer.parseInt(eccidString, 16);
byte toggleButton=0;
if ((0xff & reciver_buffer[11])==0x01) {
toggleButton =(byte)0xf0;
}
byte send_meter [] = new byte []{meterAddr,meterCmd,(byte)(regStartAddr>>8),(byte)regStartAddr,(byte)(regCount>>8),(byte)regCount,0x02,toggleButton,0x00};
ModbusCrc16 modbusCrc16 = new ModbusCrc16();
modbusCrc16.update(send_meter, send_meter.length);
crcValue=modbusCrc16.value;
byte send_control [] = new byte[]{(byte) 0x4c,0x53,(byte)0xdf,0x00,(byte)(eccid>>8),(byte)eccid,(byte)valid_data_length,(byte)(valid_data_length>>8),
meterAddr,meterCmd,(byte)(regStartAddr>>8),(byte)regStartAddr,(byte)(regCount>>8),(byte)regCount,0x02,toggleButton,0x00,(byte)crcValue,(byte)(crcValue>>8),sum1,0x0d,0x0a};
for(int i=0;i<send_control.length-3;i++)
sum1+=0xff & send_control[i];
send_control[send_control.length-3]=(byte)sum1;
sop.write(send_control, 0, send_control.length);
System.out.println("send control meter cmd finished!");
sendSocket = null;
}
else {
System.out.println("sendSocket is null!");
}

break;
default:
break;
}
}
else
break;
}
}catch (Exception e) {
e.printStackTrace();
}finally{
try {
if(socket != null) {
login_succed=false;
// ccidHashSet.remove(Integer.toHexString(ccid));
socketHashMap.remove(Integer.toHexString(ccid));
socket.shutdownInput();
socket.shutdownOutput();
br.close();
pw.close();
socket.close();
//断开连接,修改数据库状态 ccid
}
System.out.println(socket.getInetAddress()+":"+socket.getPort()+" is closed.");
} catch (Exception e2) {
e2.printStackTrace();
}

}
}


}
public static void main(String[] args)throws IOException {
// TODO Auto-generated method stub

new EchoServer().service();




}


}


以上是第一个类


package com.linksprite.devices;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

public class Ecc {

private Socket m_sock;
private InputStream m_inputStream;
private OutputStream m_outputStream;

public Ecc(Socket sock)
{
m_sock = sock;

try {
m_inputStream = m_sock.getInputStream();
m_outputStream = m_sock.getOutputStream();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

public int read(byte[] buffer)
{
try {
return m_inputStream.read(buffer);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return 0;
}
}

public void write(byte[] buffer)
{
try{
m_outputStream.write(buffer);
}
catch (IOException e)
{
e.printStackTrace();
}
}


}


这是第二个类


我没明白 如何从EchoServer里面获得CCID 然后再根据需求发送给客户端指定的数据包
我没明白这个怎么写。
但是 现在的一个问题是,我要获得的CCID 得是从之前已经连接上来的客户端的线程获取。求解 应该怎么做?
cdkx945 2012-07-02
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 的回复:]

说的不是很清楚 但是打字真的好累啊!!!
[/Quote]我直接上代码吧!
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class EchoServer {
int ccid;
public int getCcid() {
return ccid;
}
public void setCcid(int ccid) {
this.ccid = ccid;
}
//端口号
private int port=3005;
//
private ServerSocket serverSocket;
private ExecutorService executorService;
private final int POOL_SIZE = 4;
private HashMap<String, Socket> socketHashMap = new HashMap<String,Socket>();private HashMap<String,Ecc> eccHashMap = new HashMap<String,Ecc>();byte Packet_Head[]={0x4c,0x53};
byte Packet_End[]={0x0d,0x0a};

public EchoServer() throws IOException {
serverSocket = new ServerSocket(port);
executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()*POOL_SIZE);
System.out.println("服务器启动");
}

public void service() {
while (true) {
Socket socket=null;
try {
socket = serverSocket.accept(); //接收客户连接
//socket.setSoTimeout(10000); //10秒无数据传输,连接自动断掉
socket.setSoTimeout(100000);
executorService.execute(new Handler(socket)); //创建一个工作线程 ,加入到线程池
}catch (IOException e) {
e.printStackTrace();
}
}
}




class Handler implements Runnable{
private Socket socket;
private InputStream br;
private OutputStream pw;
private byte reciver_buffer []=new byte [2048];
private int recive_length;
boolean login_succed = false;
// int ccid;

public Handler(Socket socket){
this.socket = socket;
}


public int indexOf(byte data[],int length_a,byte b[],int length_b){
int i,j;
for(i=0;i<=(length_a-length_b);i++){
boolean isValid=true;
for(j=0;j<length_b;j++){
if(data[i+j]!=b[j]){
isValid=false;
break;
}
}
if(isValid){
return i;
}
}
return -1;

}
public void run(){
Socket sendSocket =null;

Ecc ecc = new Ecc(socket);
try{
System.out.println("New connection accepted"+
socket.getInetAddress()+":"+socket.getPort());
br = socket.getInputStream();
pw = socket.getOutputStream();
while(true){
recive_length=ecc.read(reciver_buffer);
if(recive_length!=-1){
int index_head=indexOf(reciver_buffer,reciver_buffer.length,Packet_Head,Packet_Head.length);
System.out.println("packet_head index is:"+index_head);
if(index_head==-1) continue;
int index_end=indexOf(reciver_buffer,reciver_buffer.length,Packet_End,Packet_End.length);
System.out.println("packet_end index is:"+index_end);
if(index_end==-1) continue;
int recive_sum = 0xff & reciver_buffer[index_end-1];
int check_sum=0;
for (int i = 2; i < recive_length - 3; i++)
{
check_sum+=0xff & reciver_buffer[i];
}
check_sum = check_sum & 0xff;
System.out.println("recive_sum is : "+ Integer.toHexString(recive_sum));
System.out.println("check_sum is : "+ Integer.toHexString(check_sum));
if((byte)recive_sum!=(byte)check_sum) continue;
System.out.println("data packet is valid!");
int packet_cmd = 0xff & reciver_buffer[3];
int packet_cmd_reserved = 0xff & reciver_buffer[4];
int recive_valid_length = ((0xff & reciver_buffer[7])<<8)+ (0xff & reciver_buffer[6]);
int valid_data_length = 0;
byte sum=0;

switch (packet_cmd) {
case 0x7e:
ccid = 0xff & reciver_buffer[5];
System.out.println("ccid is : "+ccid);
if (ccid==0x00) {
//控制客户端登陆
if(login_succed==false){
//发登陆成功回应
valid_data_length = 0x06;
byte send_longin_ack [] = new byte[]{(byte) 0x4c,0x53,(byte)0x00,0x3f,0x00,(byte)ccid,(byte)valid_data_length,(byte)(valid_data_length>>8),
0x00,0x00,0x00,0x00,0x00,0x00,sum,0x0d,0x0a};
for(int i=0;i<send_longin_ack.length-3;i++)
sum+=0xff & send_longin_ack[i];
send_longin_ack[send_longin_ack.length-3]=(byte)sum;
ecc.write(send_longin_ack);
eccHashMap.put(""+ccid+"", ecc);

login_succed = true;
socket.setSoTimeout(0);
System.out.println("ecc id:"+ccid+" longin succeed!");
}
}
else {
//ecc登陆

if(login_succed==false){
//发登陆成功回应
//登陆成功,修改数据库状态 ccid
valid_data_length = 0x06;
byte send_longin_ack [] = new byte[]{(byte)0x4c,0x53,(byte)0x00,0x3f,0x00,(byte)ccid,(byte)valid_data_length,(byte)(valid_data_length>>8),
0x00,0x00,0x00,0x00,0x00,0x00,sum,0x0d,0x0a};
for(int i=0;i<send_longin_ack.length-3;i++)
sum+=0xff & send_longin_ack[i];
send_longin_ack[send_longin_ack.length-3]=(byte)sum;
ecc.write(send_longin_ack);
login_succed = true;
System.out.println("ecc id:"+ccid+" longin succeed!");
// ccidHashSet.add(Integer.toHexString(ccid));
socketHashMap.put(Integer.toHexString(ccid), socket);
}
}

break;
case 0x7b:
//心跳包
//发心跳回应
if(login_succed==true){
valid_data_length = 0x00; byte send_heart_ack [] = new byte[]{(byte) 0x4c,0x53,(byte)0x00,0x3e,0x00,(byte)ccid,(byte)valid_data_length,(byte)(valid_data_length>>8),
sum,0x0d,0x0a};
for(int i=0;i<send_heart_ack.length-3;i++)
sum+=0xff & send_heart_ack[i];
send_heart_ack[send_heart_ack.length-3]=(byte)sum;
ecc.write(send_heart_ack);
}
a363722188 2012-07-01
  • 打赏
  • 举报
回复
说的不是很清楚 但是打字真的好累啊!!!
a363722188 2012-07-01
  • 打赏
  • 举报
回复
我来详细的说一遍: 关键代码如下
服务器端 ServerSocket ss= new ServerSocket(端口号 如1555); //创建ServerSocket对象
有啦ss 在调用ss的accept方法返回一个Socket对象 Socket s=ss.accept(); 写到这一步 服务器就阻塞到这里啦 一直等待客服端连接他
OutputStream os=s.getOutputStream();//向客户端发送信息
BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(os));

bw.write("服务器连接上.....");



客服端 Socket s=new Socket("localhost",端口号);//这个端口号一定要与服务器的端口号相同
通过s 得到一个inputstream对象 InputStream is=s.getInputStream(); 有啦InputStream 我们就可以通过bufferedReader读取服务器给客户端发来的信息 BufferedReader br=new BufferedReader
(new nputStreamReader(is)); String s=br.readLine();//s就是服务器发来的信息


其实说透啦 主要就是通过Socket类的getOutputStream();getinputStream();获得写和读的方法 其余的操作就和IO流的操作一样!!

luyuiong 2012-07-01
  • 打赏
  • 举报
回复
什么是发送指定的数据包?
一般都是发送 一个类的一个对象
该类 里面定义你想要发送的数据。
该对象中还包括该包的属性。 如:1.登陆成功 2.发送消息
你从服务器 返回该对象给客户端,客户端拿到后 看到是1 就用1的方法处理。。。。
客户端 到服务器同样原理。
cdkx945 2012-07-01
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 的回复:]

服务器端accept,客户端连接进来后,socket是双向可通信的。此时,服务器端用outputstream发送,客户端用InputStream接收就行了。
[/Quote]能具体一点吗?举个例子
cdkx945 2012-07-01
  • 打赏
  • 举报
回复
你是说 每个服务端的线程对应客户端的线程 对吗?
magong 2012-07-01
  • 打赏
  • 举报
回复
服务器端accept,客户端连接进来后,socket是双向可通信的。此时,服务器端用outputstream发送,客户端用InputStream接收就行了。

62,620

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧