search

Home  >  Q&A  >  body text

JAVA TCP长连接

做了一个指纹门锁,需要用TCP长连接进行服务端和门锁间的数据通信。
目前JAVA写socket服务端,门锁连接JAVA服务端。
服务端开了一个线程在监听门锁发来的数据(此处必须实时监听数据)
在监听的同时,若用socket发送数据的话,会出现异常报错。

第一个类负责接收socket连接

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

import com.lock.util.StaticResource;
/**
 * 侦听类
 * 不断侦听Socket连接,将连接的Socket记录,并开启线程接受传来的数据
 * @author plzwb
 */
public class ListenSocket implements Runnable{
    ServerSocket serverSocket = null;
    
    @Override
    public void run() {
        try {
            serverSocket = new ServerSocket(2333);
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("2333端口被占用");
        }
        
        while (true) {
            try {
                Socket socket = serverSocket.accept();
                StaticResource.socketList.add(socket);
                new Thread(new OpenRecordSocket(socket)).start();
                System.out.println("Socket已连接");
            } catch (IOException e) {
                e.printStackTrace();
                System.out.println("accept异常");
            }
        }
    }
}

第二个类负责不断侦听数据

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

import com.lock.util.SocketUtil;
import com.lock.util.StaticResource;

public class OpenRecordSocket implements Runnable{
    Socket socket = null;
    SocketUtil socketUtil = null;
    boolean state = true;

    
    public OpenRecordSocket(Socket socket) {
        this.socket = socket;
        socketUtil = new SocketUtil(socket);
    }
    
    @Override
    public void run() {
        while(state){
            try {
                System.out.println("准备接受");
                String text =  socketUtil.receiveData();
                System.out.println(text);
            } catch (IOException e) {
                StaticResource.socketList.remove(socket);
                state = false;
                System.out.println("Socket已经删除");
            }
        }
    }
}

一个Servlet,访问即可调用socket发送消息

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        Socket socket = StaticResource.socketList.get(0);
        SocketUtil socketUtil = new SocketUtil(socket);
        socketUtil.sendData("hello");
    }

Socket发送接收工具

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

public class SocketUtil {
    Socket socket = null;

    public SocketUtil(Socket socket) {
        super();
        this.socket = socket;
    }
    
    //发送数据
    public void sendData(String data) throws IOException {
        OutputStream outputStream = socket.getOutputStream();
        outputStream.write(data.getBytes());
    }
    
    //接收数据
    public String receiveData() throws IOException {
        InputStream inputStream = socket.getInputStream();
        byte[] buf = new byte[1024];
        int len = inputStream.read(buf);
        String text = new String(buf, 0, len);
        return text;
    }
}

异常信息如下

Exception in thread "Thread-3" 
java.lang.StringIndexOutOfBoundsException: String index out of range: -1
    at java.lang.String.checkBounds(String.java:381)
    at java.lang.String.<init>(String.java:545)
    at com.lock.util.SocketUtil.receiveData(SocketUtil.java:27)

    at com.lock.socket.OpenRecordSocket.run(OpenRecordSocket.java:25)
    at java.lang.Thread.run(Thread.java:745)


高洛峰高洛峰2940 days ago930

reply all(1)I'll reply

  • 三叔

    三叔2016-10-29 09:05:57

    定位报错的代码 String index out of range: -1 下标越界了

        at java.lang.String.(String.java:545)
        at com.lock.util.SocketUtil.receiveData(SocketUtil.java:27)

    发生在

    new String(buf, 0, len);

    说明len = -1

    也就是说inputStream.read(buf)读到了-1个字节,查阅文档

    public int read(byte[] b)

    throws IOException

    Returns:

     the total number of bytes read into the buffer, or -1 if there is 
     no more data because the end of the stream has been reached.

    返回-1的时候说明stream已经结束,很可能socket这个时候已经close

    检查socket两端的逻辑,确定在你所述的『若用socket发送数据』的时候socket的连接状态。

    学会查API文档和单步调试 :)


    reply
    0
  • Cancelreply