正在执行一个宠物项目,以便通过android设备为我的计算机创建可工作的鼠标,我在PC上运行了一个python服务器,并且android应用程序向其发送了所需的数据。

我创建此鼠标的想法是使用Motion_Event UP和MOVE在设备屏幕上记录您的手指运动,计算您的上一个和新的x,y坐标之间的差异,并将该差异发送到PC,以便它将鼠标移动到相同的模式

现在我有一些问题,从发送本身到计算,我真的希望你们的意见关于我应该如何更好地执行此算法,或者只是对我的代码做一个不好的实现。

Java的:

@Override
public boolean onTouchEvent(MotionEvent event) {
    if(event.getAction() == MotionEvent.ACTION_DOWN ){
        oldX = (int) event.getX();
        oldY = (int) event.getY();
    }
    else if(event.getAction() == MotionEvent.ACTION_MOVE ){
        newX = (int) event.getX();
        newY = (int) event.getY();

        xDiff = newX - oldX;
        yDiff = newY - oldY;
        Log.v("xdiff", ""+xDiff);
        Log.v("ydiff", ""+yDiff);
        oldX = newX;
        oldY = newY;
        a.mouse(xDiff, yDiff);
    }
    else if(event.getAction() == MotionEvent.ACTION_UP){

    }
    return true;
}

socket :
@Override
protected Void doInBackground(Void... params) {
    try {
    this.sock = new Socket("10.0.0.2", 9871);
    outToServer = new DataOutputStream(this.sock.getOutputStream());
    }
    catch (UnknownHostException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return null;
}

        public void mouse(int x, int y) {

            try {

                this.outToServer.writeBytes(""+x+","+y);


            } catch (UnknownHostException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }

python套接字:
def __init__(self, IP, port):
    try:
        self.acceptor = socket.socket()
        self.acceptor.bind((IP, port))
        self.acceptor.listen(1)
    except socket.error, e:
        print e

def start_server(self):
    try:
        print "serv up"
        self.sock, self.connecting_ip = self.acceptor.accept()
        print self.connecting_ip[0] + " connected!"

    except socket.error, e:
        print e

数据处理本身:
def mouse(self):
    try:
        while True:
            data = self.sock.recv(1024)
            if data:
                coords = data.split(",")
                x = int(coords[0])
                y = int(coords[1])
                current_x = win32api.GetCursorPos()[0]
                current_y = win32apo.GetCursorPos()[1]
                win32api.SetCursorPos((current_x+x,current_y+y))
            else:
                self.sock.close()
    except socket.error, e:
        print e

我遇到的问题是:

1)而不是像我发送的那样获取数据(“” + x +“,” + y),它将更多的数据加载到缓冲区中,并以x,y,x,y,x,y,x,y的形式显示,x,y,x,y ...
我试图弄乱缓冲区的大小,但是并没有做太多
(请注意,这很奇怪,当我在模拟器上运行应用程序时,我没有收到此错误,并且我将想要的东西完全放入x,y的缓冲区中,但是当我运行时它在我的android设备上(如果很重要,则为SGS2),数据进入掩体并立即发送所有内容)

2)我得到的另一件事是数据被“损坏”或丢失,例如发送“”而不是数字,或者发送了4和-5以4-5(而不是4,-5)发送

总而言之,我敢肯定我在这里主要是在操蛋,我希望有人能阐明我该如何去做。

UDP实现:
@Override
protected Void doInBackground(Void... params) {
    try {

        this.clientSocket = new DatagramSocket();
            this.IPAddress = InetAddress.getByName("10.0.0.2");
            this.sendData = new byte[1024];

    }
    catch (UnknownHostException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return null;
}

        public void mouse(int x, int y) {

            try {

                  String sentence = "{" + x + "," + y + "}";
                  this.sendData = sentence.getBytes();
                  DatagramPacket sendPacket = new DatagramPacket(this.sendData, this.sendData.length, this.IPAddress, 9871);
                  this.clientSocket.send(sendPacket);

            } catch (UnknownHostException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }

python udp serv:
import socket

PORT = 9871
IP = socket.gethostbyname(socket.gethostname())

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP
sock.bind((IP, PORT))
print "Server %s" % IP

while True:
        data, addr = sock.recvfrom(1024) # buffer size is 1024 bytes
        if data:
            print "received message:", data
        else:
            print "dead"

最佳答案

TCP是流协议(protocol)。这意味着当您多次send()(或者在您的情况下为.writeBytes())时,不同调用的参数之间没有边界。

例如,当您发送:

send("1,2");
send("-3,4");
send("5,6");
send("-7,8");

然后,这可能会到达另一端,如下所示:
"1,2-3,45,6-7,8"

如果要使用TCP并保留消息之间的边界,则需要在协议(protocol)中添加一层以提供此功能。有两种传统方法可以实现此目的:
  • 使用分隔符字节标记消息的结尾。确保有效消息不会包含分隔符字节。
  • 在每条消息之前添加一个固定长度的长度字段,例如一个32位整数。

  • 在您的情况下,通过简单地添加换行符来选择第一个选项就可以解决问题:
    send("1,2\n");
    send("-3,4\n");
    send("5,6\n");
    send("-7,8\n");
    

    这将以类似以下方式到达另一端:
    "1,2\n-3,4\n5,6\n-7,8"
    

    阅读时,您可以使用换行符来重建原始消息。

    警惕线条不完整。当我们说数据必须以"1,2\n-3,4\n5,6\n-7,8"的形式到达时,我们在上面进行了一些简化。它也可能一次到达:
    "1,2\n-3," // from the first read call
    "4\n5,6\n-7,8" // from the second read call
    

    从TCP流读取消息时,需要将读取的内容放入缓冲区。在处理完一条完整的消息之前(或直到某些原因导致您想要完全放弃连接之前),您无法丢弃数据。例如,如果缓冲区以不完整的消息"-3,"结尾,那么您需要阅读直到拥有其余消息:"4\n"

    另一种可能合适的解决方案是使用数据报协议(protocol)(例如UDP),其中发送方的消息确实确实与接收方的消息相对应。 (请注意,TCP和UDP之间还有其他非常明显的区别!请不要仅基于此进行切换。)

    09-16 03:16
    查看更多