【问题标题】:TCP socket Transfer data from PC to android device (Android NDK)TCP socket 将数据从 PC 传输到 android 设备 (Android NDK)
【发布时间】:2012-08-08 20:11:47
【问题描述】:

我正在努力实现Android设备(客户端)和PC(服务器)之间的TCP套接字,代码由c++(Android NDK)实现。

一切正常,当我运行到服务器端时,输出“服务器启动”它等待连接到客户端。另一边,当我为客户端运行时,它一直工作,直到连接到服务器,我发现这个错误“socket connect to server error

谁能告诉我想要的是什么问题?

我想将矩阵 16*16 从服务器传输到客户端并形成客户端到服务器的想法......

服务器端:

MyServerThread::MyServerThread()
{
    startServer();
}
void MyServerThread::run()
{
    //std::cout<<"hi"<<std::endl;
    for(int i=0;i<16;i++)
        matrix[i]=(float)i;
    memcpy(buf,matrix,4*16);
    sendMSG();
}

//TCP socket
/* now create the server socket
   make it an IPV4 socket (PF_INET) and stream socket (TCP)
   and 0 to select default protocol type */
if ( (server_skt = socket(AF_INET, SOCK_STREAM, 0)) == -1 ){
    std::cerr<<"socket creation failed"<<std::endl;
    exit(1);
}

//Initail, bind to port
/* now fill in values of the server sockaddr_in struct
   s_addr and sin_port are in Network Byte Order (Big Endian)
   Since Intel CPUs use Host Byte Order (Little Endian), conversion
   is necessary (e.g. htons(), and htonl() */
server_addr.sin_family = AF_INET;//IPv4
server_addr.sin_port = htons(PORT);
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
memset(server_addr.sin_zero, 0, 8);

//binding

 /* now bind server port
       associate socket (server) with IP address:port (server_addr) */

if ( bind(server_skt, (struct sockaddr*)&server_addr, sizeof(struct sockaddr)) == -1 ){
    std::cerr<<"socket bind failed"<<std::endl;
    exit(1);
}

int queueSize=1;
//Start listening, wait for connection from client with a pending queue of size
if ( listen(server_skt, queueSize) == -1 ){
    std::cerr<<"socket listen failed"<<std::endl;
    exit(1);
}

//Wait for connect!
bool gotClient=false;
while(!gotClient){
    sin_size = sizeof(struct sockaddr_in);
    socklen_t temp=sin_size;
    std::cout<<"server starts"<<std::endl;
    if ( (client_skt = accept(server_skt, (struct sockaddr*)&clients_addr, &temp)) == -1 ){
        std::cerr<<"socket error"<<std::endl;}
    else
    {
        gotClient=true;
        std::cout<<"Got client"<<std::endl;
    }
}

    void MyServerThread::sendMSG()
{
    if ( (numbytes = send(client_skt, buf, strlen(buf),0)) == -1){
        std::cerr<<"server, normal send error"<<std::endl;
        exit(1);
    }
}

void MyServerThread::recvMSG()
{
    if ( (numbytes = recv(client_skt, buf, bufferSize,0)) == -1 ){
        std::cerr<<"server, normal recv error"<<std::endl;
        exit(1);
    }
}

客户端:

Client::Client()
{

}
void Client::startClient()
{
    /* now fill in sockaddr_in for remote address */
    serv_addr.sin_family = AF_INET;
    /* save the server IP (input from Java */
    serv_addr.sin_addr.s_addr = inet_addr(serverIP);
    /* set port */
    serv_addr.sin_port = htons(PORT);
    memset(serv_addr.sin_zero, 0, 8);

    /* create local stream socket */
    client_skt = socket(PF_INET, SOCK_STREAM, 0);
    if (client_skt < 0) {
        __android_log_print(ANDROID_LOG_ERROR,"jni client","socket creation error");
        exit(-1);
    }

    /* bind local socket to any port number */
    local_addr.sin_family = AF_INET;
    local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    //local_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    local_addr.sin_port = htons(PORT);
    memset(local_addr.sin_zero, 0, 8);

    rc = bind(client_skt, (struct sockaddr *) &local_addr, sizeof(local_addr));

    if (rc < 0)
    {
        __android_log_print(ANDROID_LOG_ERROR,"jni client","socket bind error");
        exit(1);
    }
    __android_log_print(ANDROID_LOG_INFO,"jni client","client start finished");


}
void Client::connectServer()
{
    __android_log_print(ANDROID_LOG_INFO,"jni client","connect to server starts");
    /* connect to server */
    rc = connect(client_skt, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
    if (rc < 0)
    {
        __android_log_print(ANDROID_LOG_ERROR,"jni client","socket connect to server error");
        exit(1);
    }
    __android_log_print(ANDROID_LOG_ERROR,"jni client","server connected");
}
void Client::sendMSG()
{
    if ( (numbytes = send(client_skt, "hello!", strlen("hello!"),0) )== -1 ){
        __android_log_print(ANDROID_LOG_ERROR,"jni client","send error");
        //exit(1);
    }

}
void Client::recvMSG()
{
    if ( (numbytes = recv(client_skt, buf, bufferSize,0) ) == -1 ){
        __android_log_print(ANDROID_LOG_ERROR,"jni client","recv error");
        //exit(1);
    }
    else
    {
        memcpy (matrix, buf, numbytes);
        for(int i=0;i<4;i++)
            __android_log_print(ANDROID_LOG_INFO,"matrix","%f, %f, %f, %f",matrix[i*4],matrix[i*4+1],matrix[i*4+2],matrix[i*4+3]);
    }
}

问候,

【问题讨论】:

  • 在客户端,你是在connectServer()之前运行startClient()吗?
  • 不,我在客户端之前运行服务器。
  • 我的意思是,在客户端,您是否同时运行了 startClient 和 connectServer(按此顺序)?
  • 是的,我运行启动客户端,一切正常,我可以在 LogCat 上看到“服务器 IP:137.110.119.202 客户端启动完成”,然后当连接服务器功能启动应用程序时自动关闭

标签: android c++ sockets android-ndk


【解决方案1】:

如果客户端和服务器在同一台机器上,您的connect() 可能会因 EADDRINUSE(本地地址已在使用)而失败,因为您将客户端和服务器绑定到相同的端口号:

local_addr.sin_port = htons(PORT);

编辑客户端代码,将客户端绑定到端口 0(这意味着内核将为您选择一个未使用的临时端口),然后重试。

即使这不是您遇到的确切问题,您也应该始终记录库函数返回的错误。在connect() 失败后,记录strerror(errno) 的值。

【讨论】:

  • 我在客户端将 PORT 更改为 0,但我有同样的错误。我在 PC 上运行服务器,在安卓设备上运行客户端。
  • 您是否将PORT 更改为0(这将失败,因为您将连接到服务器上的端口0),或者将上面的行更改为local_addr.sin_port = htons(0)
  • 另外,你能登录 strerror(errno) 看看确切的 connect 错误是什么吗?
  • 客户端和服务器的IP地址是什么?服务器(PC)是否运行防火墙?
  • 服务器IP我用这一行 server_addr.sin_addr.s_addr = htonl(INADDR_ANY); IP 地址是 137.110.119.202,另一边是 IP 地址,我把它放在主要活动上 public void onClick(View v) { // TODO 自动生成的方法 stub String IP=new String("137.110.119.202" ); NativeLib.getServerIPandStartClient(IP);全部 8888 的 PORT 和在 PC 上运行的 fairwall,但我尝试了其他示例,它们都使用这个端口。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-21
  • 1970-01-01
  • 2015-08-05
  • 1970-01-01
  • 2011-04-17
  • 1970-01-01
相关资源
最近更新 更多