2010-12-11 11 views
5

से वाईफाई टीसीपी कनेक्शन में प्रेषित कचरा डेटा मैं इस विशेष मुद्दे का समाधान ढूंढने में सक्षम नहीं हूं, और मैं इस विशेष मुद्दे का समाधान नहीं ढूंढ पाया। मुझे माफ़ कर दो अगर यह एक नौसिखिया गलती है, तो मैं स्कूल से बाहर ताजा हूं इसलिए मैं मोबाइल डिवाइस प्रोग्रामिंग पर पकड़े जाने के लिए जितनी किताबें पढ़ सकता हूं।डेस्कटॉप से ​​एंड्रॉइड

लक्ष्य: एक एंड्रॉयड आधारित क्लाइंट वायरलेस (802.11 b/g) है, जो तब प्रक्रिया कहा जाएगा उपयोगकर्ता के लिए उत्पादन के लिए डेटा के लिए एक पीसी आधारित सॉकेट सर्वर से संचारित डेटा।

समस्या: गलत कचरा डेटा की एक बड़ी राशि एंड्रॉयड फोन पर इनपुट धारा बफर में प्राप्त नहीं हुआ।

प्रक्रिया: मैंने कोड के तीन अलग-अलग टुकड़े लिखे और/या संशोधित किए हैं। सबसे पहले सर्वर साइड प्रोग्राम मेरे लैपटॉप पर चल रहा है। मूल स्रोत कोड यहां पाया जा सकता है: beej.us/guide/bgnet/examples/server.c (बीज़ को उनके स्रोत कोड के लिए धन्यवाद!)। मैंने इसे चेतावनियों/त्रुटियों को हटाने के लिए संशोधित किया है, और परीक्षण उद्देश्यों के लिए अपना स्वयं का सतत डेटा इनपुट पाश जोड़ा है।

/* A simple server in the internet domain using TCP 
    The port number is passed as an argument */ 
#include <unistd.h> 
#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 

void error(char *msg) 
{ 
    perror(msg); 
    exit(1); 
} 

int main(int argc, char *argv[]) 
{ 
    int sockfd, newsockfd, portno; //, clilen; 

    //Modified this fromt he original author's code, as 
    //the function is looking for clilen to be of type 
    //socklen_t, not int 
    socklen_t clilen; 

    char buffer[256]; 
    struct sockaddr_in serv_addr, cli_addr; 
    int n; 

    if (argc < 2) 
    { 
     fprintf(stderr,"ERROR, no port provided\n"); 
     exit(1); 
    } 

    sockfd = socket(AF_INET, SOCK_STREAM, 0); 
    if (sockfd < 0) 
     error("ERROR opening socket"); 

    bzero((char *) &serv_addr, sizeof(serv_addr)); 
    portno = atoi(argv[1]); 
    serv_addr.sin_family = AF_INET; 
    serv_addr.sin_addr.s_addr = INADDR_ANY; 
    serv_addr.sin_port = htons(portno); 

    if (bind(sockfd, (struct sockaddr *) &serv_addr, 
       sizeof(serv_addr)) < 0) 
       error("ERROR on binding"); 

    //Added this for some clarity 
    printf("Starting to listen on the socket now..\n"); 
    listen(sockfd,5); 


    clilen = sizeof(cli_addr); 

    newsockfd = accept(sockfd, 
       (struct sockaddr *) &cli_addr, 
       &clilen); 

    //Let me know a socket connection has been established 
    printf("Socket established!\n"); 


    if (newsockfd < 0) 
      error("ERROR on accept"); 

    bzero(buffer,256); 

    //Don't want this socket to block and read, only to write 
    //Modified from the original author 
    //n = read(newsockfd,buffer,255); 

    //if (n < 0) error("ERROR reading from socket"); 
    //printf("Here is the message: %s\n",buffer); 

    //n = write(newsockfd,"Hello, socket!",18); 

    const int SIZE_OF_STRING = 30; 
    char string[SIZE_OF_STRING]; 
    int i = 0; 

    for (i = 0; i < SIZE_OF_STRING; ++i) 
    { 
     string[i] = '\0'; 
    } 

    //Ask input from the user until the word "quit" is seen 
    //then close the socket 
    while (!strstr(string, "quit")) 
    { 
     printf("Please enter something to send to the phone.\n"); 
     scanf("%s", string); 
     strcat(string, "\n"); 
     n = write(newsockfd, string, sizeof(string)); 
     if (n < 0) error("ERROR writing to socket"); 
    } 

    printf("\n\nexiting..\n"); 

    close(newsockfd); 
    close(sockfd); 

    return 0; 
} 

यहाँ और एंड्रॉयड कोड है:: यहाँ संशोधित कोड है

public class SmartSawLineDrawSocketThread extends Thread 
{ 

    private Handler smartSawMainThreadCommunicationHandle_; 
    private Socket smartSawSocketHandle_; 
    private InputStream smartSawSocketInputStreamHandle_; 
    private BufferedReader smartSawSocketInputBuffer_; 
    private InputStreamReader smartSawSocketInputStreamReader_; 
    private boolean threadRunning_ = false; 
    private boolean isConnected_; 
    private char buffer[] = new char[50]; 



    //Grab the thread's communication handle for use with sending messages to the UI 
    //Thread 
    public SmartSawLineDrawSocketThread(Handler handle) 
    { 
     smartSawMainThreadCommunicationHandle_ = handle; 
     threadRunning_ = true; 
     isConnected_ = false; 
    } 

    //Attempt a connection to the host 
    public int SmartSawLineDrawSocketThreadConnect(String hostIP, String hostPort) 
    { 
     int rval = 0; 
     Log.i("info", "hostIP = " + hostIP); 
     Log.i("info", "hostPort = " + Integer.parseInt(hostPort.trim())); 
     try 
     { 
      smartSawSocketHandle_ = new Socket(hostIP.trim(), Integer.parseInt(hostPort.trim())); 
      if (rval == 0) 
      { 
       smartSawSocketInputBuffer_ = new BufferedReader(new InputStreamReader(smartSawSocketHandle_.getInputStream())); 
       smartSawSocketInputStreamReader_ = new InputStreamReader(smartSawSocketHandle_.getInputStream()); 
       if (smartSawSocketInputBuffer_ != null) 
       { 
        isConnected_ = true; 
       } 
       else 
       { 
        Log.e("error", "Input buffer pointer was null!"); 
       } 
      } 
     } 
     catch (UnknownHostException e) 
     { 
      rval = 1; 
      Log.i("info", "unknown host message e when connecting:" + e); 
      e.printStackTrace(); 
      isConnected_ = false; 
     } 
     catch (IOException e) 
     { 
      rval = 2; 
      Log.i("info", "unknown IOException e when connecting:" + e); 
      e.printStackTrace(); 
      isConnected_ = false; 
     } 
     catch (SecurityException e) 
     { 
      rval = 3; 
      Log.i("info", "Need to set a security setting somewhere"); 
     } 


     Log.i("info", "Rval returned with " + rval);  

     return rval; 
    } 

    //Disconnect from the server 
    public void SmartSawLineDrawSocketThreadDisconnect() 
    { 
     try 
     { 
      smartSawSocketHandle_.close(); 
      isConnected_ = false; 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } 

    //Once the thread has started running, make sure we're connected, and start 
    //trying to listen for messages 
    @Override 
    public void run() 
    { 
     Log.i("info", "Made it into the run() loop of the thread."); 
     while (threadRunning_) 
     { 
      if (isConnected_ == true) 
      { 
       try 
       { 
        if (smartSawSocketInputStreamReader_.ready() == true) 
        //(smartSawSocketInputBuffer_.ready() == true) 
        { 
         int numread = 0; 
         numread = smartSawSocketInputStreamReader_.read(buffer); 

         Log.i("info", "amount of characters read in: " + numread); 

         Message mainThreadMessage_ = Message.obtain(); 
         Bundle mainThreadDataBundle_ = new Bundle(); 
         mainThreadDataBundle_.putString("Zero", new String(buffer)); //smartSawSocketInputBuffer_.readLine()); 
         mainThreadMessage_.setData(mainThreadDataBundle_); 
         mainThreadMessage_.setTarget(smartSawMainThreadCommunicationHandle_); 
         mainThreadMessage_.sendToTarget(); 
         Log.i("info", "Received a string! Sent this to main thread: " + mainThreadDataBundle_.getString("Zero")); 


        } 
       } 
       catch (IOException e) 
       { 
        Log.i("info","IO Exception in thread main loop, e was: " + e); 
       } 
      } 


     } 

    } 
} 

होमवर्क और टेस्ट: मैं सफलतापूर्वक एक स्ट्रिंग संचारित कर सकते हैं, लेकिन उसके बाद सब कुछ में अस्पष्ट कचरा है पीसी-एंड्रॉइड कनेक्शन। पहले अपना होमवर्क करना चाहते हैं, मैं सर्वर साइड कोड को खत्म करना चाहता था। मैंने बीज के क्लाइंट साइड कोड (beej.us/guide/bgnet/examples/client.c) लिया और इसे एक अच्छा श्रोता होने के लिए संशोधित किया। मैं एक पीसी-पीसी आधारित टीसीपी कनेक्शन पर क्लाइंट को कई तारों को प्रेषित करने में सक्षम था। मैंने क्लाइंट के आउटपुट को एक फाइल में रीडायरेक्ट किया, और इसे हेक्स एडिटर के तहत खोला। लो और देखो, कोई गलत डेटा नहीं मिला। मैंने इसका परीक्षण 802.11 बी/जी राउटर से जुड़े लैपटॉप के साथ किया, और एक हार्ड वायर्ड डेस्कटॉप क्लाइंट होने के साथ। मैंने हार्डवेयर समस्याओं को समाप्त कर दिया है, और सर्वर पक्ष पर परीक्षण कोड मुद्दों को समाप्त कर दिया है। यह कहीं और होना चाहिए कि मैं एंड्रॉइड क्लाइंट साइड कोड कैसे कार्यान्वित कर रहा हूं। मैंने स्वचालित इनपुट करने के लिए स्वचालित BufferedReader क्लास की कोशिश की, साथ ही इनपुट इनपुट मैन्युअल रूप से इनपुट इनपुट को संभालने का प्रयास किया। दोनों पहली स्ट्रिंग के बाद एक ही कचरा उत्पादन प्राप्त करते हैं। इससे मुझे विश्वास होता है कि यह सॉकेट की इनपुट स्ट्रीम में कहीं है, लेकिन मैं इसे कैसे ठीक करूँगा? क्या किसी के पास कोई सुझाव है?

/* 
** client.c -- a stream socket client demo 
*/ 

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <errno.h> 
#include <string.h> 
#include <netdb.h> 
#include <sys/types.h> 
#include <netinet/in.h> 
#include <sys/socket.h> 

#include <arpa/inet.h> 

#define PORT "27015" // the port client will be connecting to 

#define MAXDATASIZE 100 // max number of bytes we can get at once 

// get sockaddr, IPv4 or IPv6: 
void *get_in_addr(struct sockaddr *sa) 
{ 
    if (sa->sa_family == AF_INET) { 
     return &(((struct sockaddr_in*)sa)->sin_addr); 
    } 

    return &(((struct sockaddr_in6*)sa)->sin6_addr); 
} 

int main(int argc, char *argv[]) 
{ 
    int sockfd, numbytes; 
    char buf[MAXDATASIZE]; 
    struct addrinfo hints, *servinfo, *p; 
    int rv; 
    char s[INET6_ADDRSTRLEN]; 

    if (argc != 2) { 
     fprintf(stderr,"usage: client hostname\n"); 
     exit(1); 
    } 

    memset(&hints, 0, sizeof hints); 
    hints.ai_family = AF_UNSPEC; 
    hints.ai_socktype = SOCK_STREAM; 

    if ((rv = getaddrinfo(argv[1], PORT, &hints, &servinfo)) != 0) { 
     fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); 
     return 1; 
    } 

    // loop through all the results and connect to the first we can 
    for(p = servinfo; p != NULL; p = p->ai_next) { 
     if ((sockfd = socket(p->ai_family, p->ai_socktype, 
       p->ai_protocol)) == -1) { 
      perror("client: socket"); 
      continue; 
     } 

     if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) { 
      close(sockfd); 
      perror("client: connect"); 
      continue; 
     } 

     break; 
    } 

    if (p == NULL) { 
     fprintf(stderr, "client: failed to connect\n"); 
     return 2; 
    } 

    inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr), 
      s, sizeof s); 
    printf("client: connecting to %s\n", s); 

    freeaddrinfo(servinfo); // all done with this structure 

    //Modified from the original to spit out all strings transmitted from the server, then close the socket 
    //when finished. 
    while (!strstr(buf, "close")) 
    { 
     numbytes = recv(sockfd, buf, MAXDATASIZE-1, 0); 
     if (numbytes) 
     { 
      printf("Received: \n"); 
      printf("%s", buf); 
      printf("\n"); 
     } 
    } 

    if ((numbytes = recv(sockfd, buf, MAXDATASIZE-1, 0)) == -1) { 
     perror("recv"); 
     exit(1); 
    } 

    buf[numbytes] = '\0'; 

    printf("client: received '%s'\n",buf); 

    close(sockfd); 

    return 0; 
} 

मदद के लिए धन्यवाद:

यहाँ पीसी आधारित क्लाइंट पक्ष परीक्षण के लिए कोड है! Moscro

+0

FYI करें अगले न्यू लाइन चरित्र अप करने के लिए पढ़ता है का उपयोग करें, जबकि आधिकारिक तौर पर समर्थित नहीं आप NDK के साथ अपने पीसी ग्राहक परीक्षण संकलन कर सकते हैं अकेले स्टैंड के रूप में जीसीसी निष्पादन योग्य और फोन पर कोशिश करें। इसके अलावा एंड्रॉइड के कुछ बिल्डों में नेटकैट (एनसी) कमांड लाइन निष्पादन योग्य है जो दोनों सिरों पर परीक्षण के लिए बहुत अच्छा है। –

+0

धन्यवाद क्रिस! मैं इसे अपने अगले दौर में देख लूंगा। मेरे पास पहले से ही बुनियादी ढांचा स्थापित है, इसलिए मैं इसे छोड़ दूंगा क्योंकि यह अभी के लिए है, लेकिन यह बाद में काम में आएगा। – moscro

उत्तर

1

ग्राहक:

आप स्ट्रिंग के बाद से बफर के सभी नहीं भरा गया हो सकता है new String(buffer, 0, numread) का उपयोग कर बनाने चाहिए, ताकि read() द्वारा ओवरराइट नहीं मौजूदा वर्ण स्ट्रिंग में दिखाई देगा।

आपको numread == -1 के लिए भी जांच करनी चाहिए, क्योंकि इससे कनेक्शन बंद हो जाता है।

सर्वर:

sizeof(some_array) पूरे सरणी, अपने सर्वर 30 बाइट्स हर बार भेज रहा है जिसका मतलब है कि के आकार (बाइट्स में) देता है। उनमें से अधिकतर शून्य (\0) होंगे जो बताते हैं कि सी क्लाइंट क्यों काम करता है, क्योंकि printf मानता है कि पहला नल बाइट स्ट्रिंग के अंत को इंगित करता है। जावा, हालांकि, संभवतः लॉग बाइट में अतिरिक्त बाइट कचरा के रूप में क्यों दिखाई देता है।

एक समाधान हो सकता है:

  • , सर्वर को संशोधित समाप्त \n सहित संदेश में पात्रों की सही संख्या है, जो ग्राहक में strlen(string) + 1
  • तो होगा भेजने के लिए दूसरे InputStreamReader खाई और बस BufferedReader के readLine() विधि है, जो
+0

आह, मेरी गलती, मुझे लॉग आउटपुट शामिल करना चाहिए था। यहां एक लॉग शब्द है जो मुझे एक शब्द दर्ज करने के बाद मिलता है: 12-11 11: 28: 56.610: जानकारी/जानकारी (512): एक स्ट्रिंग प्राप्त हुई! इसे मुख्य धागे में भेजा गया: हैलो 12-11 11: 28: 56.610: जानकारी/जानकारी (512): ÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀ 12-11 11: 2 9: 26.710: जानकारी/जानकारी (512): वर्णों की संख्या में पढ़ा गया: 30 और यहां एक और शब्द है: 12-11 11: 2 9: 26.720: जानकारी/जानकारी (512): एक स्ट्रिंग प्राप्त हुई! इसे मुख्य धागे में भेजा गया: परीक्षण 12-11 11: 2 9: 26.720: जानकारी/जानकारी (512): ÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀ जानकारी/जानकारी (512): 30 – moscro

+0

क्योंकि संख्या को 30 पर सेट किया जा रहा है आउटपुट के लिए 5, 4, या -1 के बजाय, यह मुझे विश्वास दिलाता है कि यह स्ट्रिंग प्रारंभिक समस्या या निष्क्रिय टीसीपी सॉकेट नहीं है। इस तरह के लगातार कचरा डेटा के लिए कोई भी संभावित कारण? – moscro

+0

हां, आप हर बार 30 बाइट भेज रहे हैं और उनमें से अधिकांश कचरा हैं :) अद्यतन उत्तर देखें। – SimonJ

संबंधित मुद्दे