먼저

 

----------------------GetContactsActivity.java----------

 

 

package com.android.socket;
import java.util.ArrayList;
import android.app.Activity;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;

public class GetContactsActivity extends Activity {
 ListView listPerson;
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        listPerson = (ListView)findViewById(R.id.android_list1);
        Button btn = (Button)findViewById(R.id.Button01);
     btn.setOnClickListener(new OnClickListener(){
     public void onClick(View v){
     getList();
     TCPclient tp = new TCPclient(listPerson.toString());
     tp.run();
     }
     });
    
 }     
   
    public ArrayList getList(){          
     Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
     
     String[] projection = new String[] {      
       ContactsContract.CommonDataKinds.Phone.NUMBER,
       ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME
     };
     
     String[] selectionArgs = null;

     //이름순으로 정렬
     String sortOrder = ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME +
     " COLLATE LOCALIZED ASC";
     //조회해서 가져온다(Cursor 사용)
     Cursor contactCursor = managedQuery(uri, projection, null, selectionArgs, sortOrder);
        //정보를 담을 array 설정
     ArrayList persons = new ArrayList();
     if(contactCursor.moveToFirst()){     
      do{
       persons.add(contactCursor.getString(1) + "@"+ contactCursor.getString(0) + "#");      
      }while(contactCursor.moveToNext());
      persons.add("END");
     } 
        //리스트에 연결할 adapter 설정    
     ArrayAdapter adp = new ArrayAdapter(this, android.R.layout.simple_list_item_1, persons);
        //리스트뷰에 표시
     listPerson.setAdapter(adp);
     return persons;
    }
   
   
   
    protected void onStop()
    {
       
        // 상위 클래스의 onStop 메소드를 수행시킨다.
        super.onStop();
    }
  }
 
---------TCPclient.java---------------

 

package com.android.socket;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.util.ArrayList;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

  public class TCPclient implements Runnable {
  private static final String serverIP = "192.168.0.7"; // ex: 192.168.0.100
  private static final int serverPort = 8000; // ex: 5555
  private String msg;
  //private String return_msg;
  final static byte NM_SEND_OS_TYPE = 1;
  final static byte NM_SEND_MESSAGE = 2;
  // 소켓과 스트림 변수들
  private Socket m_client_socket = null;
  private BufferedOutputStream m_out_stream = null;
  private InputStream m_in_stream = null;
 
  // 쓰레드 변수
  private Thread m_client_thread;

  // 추가 쓰레드에서 출력할 문자열을 저장하는 변수
  private String m_recv_string;
  private String m_debug_string;

  public TCPclient(String msg){
  // this.msg = _msg;
  }

public void run() {
   try {
     
    // IP 주소와 포트 번호를 관리하는 객체를 생성한다.
       SocketAddress sock_addr = new InetSocketAddress("192.168.10.110", 8000);
       // 소켓을 생성한다.
       m_client_socket = new Socket();
       // 수신 버퍼 크기를 1024 바이트로 설정한다.
       m_client_socket.setReceiveBufferSize(1024);
       // 송신 버퍼 크기를 1024 바이트로 설정한다.
       m_client_socket.setSendBufferSize(1024);
       // 소켓을 닫을 때 TIME_OUT 에 저장해둔 밀리세컨만큼 대기한 후 닫는다.
       m_client_socket.setSoLinger(true, 5000);
       // 15분간 수신되는 데이터가 없으면 연결이 자동으로 끊긴다.
       m_client_socket.setSoTimeout(1000*60*15);
      
       // 서버와 연결을 시도한다. TIME_OUT 시간 내에 응답이 오지 않으면 연결을 포기한다.
       m_client_socket.connect(sock_addr, 5000);
      
       // 연결된 경우
       if(m_client_socket != null && m_client_socket.isConnected()){
           // 연결 성공 메세지가 텍스트뷰에 출력되도록 m_debug_run 인터페이스를 메인 쓰레드에 전달한다.
           m_debug_string = "Connect Server!!";

           // 소켓의 입력 스트림과 출력 스트림을 얻는다.
           m_out_stream = new BufferedOutputStream( m_client_socket.getOutputStream() );
           m_in_stream = m_client_socket.getInputStream();
          
        // 바이트의 사이즈를 저장한다.
           // 안드로이드의 기반인 리눅스와 윈도우즈는 Byte Ordering 이 다르기때문에
           // 2바이트의 데이터를 송수신할 때 1바이트씩 값을 바꿔주어야 한다.
           int data_size = 1;
           byte[] size = new byte[2];
           size[0] = (byte)data_size;
           size[1] = (byte)(data_size >> 8);               

           // 서버에 운영체제 타입을 전송한다.
           m_out_stream.write(NM_SEND_OS_TYPE);
           m_out_stream.write(size);
           m_out_stream.write(2); // Android
           m_out_stream.flush();
          
           // 서버의 데이터를 수신한다.
           onReadStream();
       }
   } catch (Exception e) {
       // 최상위 예외 클래스로 쓰레드에서 발생하는 모든 예외를 동일하게 처리한다.
       m_debug_string = e.getMessage();
   } finally {
       try {
           if(m_client_socket != null) {
               if(m_out_stream != null) {
                   // 출력스트림을 닫는다.
                   m_out_stream.close();
               }
               if(m_in_stream != null) {
                   // 출력스트림을 닫는다.
                   m_in_stream.close();
               }
          
               // 소켓을 닫는다.
               m_client_socket.close();
               m_client_socket = null;
           }
       } catch (IOException e) {       
       }

   }
   if(m_client_socket != null && m_client_socket.isConnected() && !m_client_socket.isClosed()){
       try {
          
        GetContactsActivity temp = new GetContactsActivity();
       
       
           byte[] send_packet = temp.getList().toString().getBytes();
        
        
           // 바이트의 길이를 얻는다.
           int data_size = send_packet.length;
          
           // 바이트의 사이즈를 저장한다.
           // 안드로이드의 기반인 리눅스와 윈도우즈는 Byte Ordering 이 다르기때문에
           // 2바이트의 데이터를 송수신할 때 1바이트씩 값을 바꿔주어야 한다.
           byte[] size = new byte[2];
           size[0] = (byte)data_size;
           size[1] = (byte)(data_size >> 8);
          
           // 메세지 번호를 쓴다.
           m_out_stream.write(NM_SEND_MESSAGE);
           // 크기 정보를 쓴다.
           m_out_stream.write(size);
           // byte 배열을 쓴다.
           m_out_stream.write(send_packet);
           // 스트림에 쓰여진 정보를 서버로 전송한다.
           m_out_stream.flush();
       } catch(IOException e) {
          
       }
   }
  
// 소켓이 제거되지 않은 경우
   if(m_client_socket != null){
       try {
           // 입출력 스트림의 무효화 작업을 수행한다. 추가된 쓰레드에서 입력 스트림이 read 메소드에
           // 대기 상태가 걸려있기때문에 이 함수를 호출하여 스트림을 무효화한다.
           if(m_in_stream != null) m_client_socket.shutdownInput();
           if(m_out_stream != null) m_client_socket.shutdownOutput();

           // 쓰레드가 수행중인 경우
           if(m_client_thread.isAlive()){
               // 추가된 쓰레드에 인터럽트를 건다.
               m_client_thread.interrupt();
               // 쓰레드가 인터럽트를 감지하여 종료할때까지 기다린다.
               m_client_thread.join();
           }
       } catch (Exception e) {
       }
   }
}
 

  public void onReadStream() throws IOException
  {
      byte msg_id;
      byte[] size = new byte[2];
     
      // 쓰레드에 인터럽트가 발생하지 않으면 반복한다.
      while (!m_client_thread.isInterrupted()) {
          // 메세지 번호를 읽는다.
          msg_id = (byte)m_in_stream.read();
          // 채팅 정보가 수신된 거라면..
          if(msg_id == NM_SEND_MESSAGE){
              // 크기 정보가 저장된 2바이트를 읽는다.
              if(m_in_stream.read(size) == 2){
                  // 안드로이드의 기반인 리눅스와 윈도우즈는 Byte Ordering 이 다르기때문에
                  // 2바이트의 데이터를 송수신할 때 1바이트씩 값을 바꿔주어야 한다.
                  int data_size = 0;
                  data_size = size[1];
                  data_size = data_size << 8;
                  data_size = data_size | size[0];
                 
                  // 데이터 크기만큼 배열을 할당한다.
                  byte[] data = new byte[data_size];
                  // 데이터 크기만큼 데이터를 읽는다.
                  if(m_in_stream.read(data) == data_size){
                      // 바이트 데이터를 문자열로 변환한다.
                      m_recv_string = new String(data);
                     
                  }
              }
          }
      }
  }

}

 

-----------------서버 파일----------------------

 

--------------main.cpp---------------------

 

 

#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#define _CRT_SECURE_NO_WARNINGS
#define BUF_LEN 18384
// WinSock DLL을 사용할 버전
#define VERSION_MAJOR         2
#define VERSION_MINOR         0
#include <string.h>
FILE *pFile;

typedef struct member{

 char name[15];
 char number[15];
}MEMBER;

int main(int argc, char* argv[])
{
 MEMBER members[500];
 
 WORD VersionRequested = MAKEWORD(VERSION_MAJOR, VERSION_MINOR);
 WSADATA       WsaData;            // receives data from WSAStartup
 struct sockaddr_in server_addr, client_addr; // socket address
 SOCKET server_fd, client_fd;  // socket handle
 char buf[BUF_LEN];
 char temp_buf[BUF_LEN];
 memset(buf, 0, sizeof(char)* BUF_LEN);
 memset(temp_buf, 0, sizeof(char)* BUF_LEN);
 memset(members, 0, sizeof(MEMBER)* 500);
 int len, msg_size;
 int i=0;
 char *ptr;
 //char *p;
 // Load WinSock DLL

 if ( WSAStartup(VersionRequested, &WsaData) != 0 ) {  
  return -1;
 }

 // socket 생성
 server_fd = socket( PF_INET, SOCK_STREAM, 0 );
 memset( &server_addr, 0, sizeof(struct sockaddr) );
 server_addr.sin_family = AF_INET;
 server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
 server_addr.sin_port = htons(atoi(argv[1]));
 // bind() 호출
 if( bind(server_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) < 0 ){
   printf("Server: Can't bind local address.\n");
  exit(0);
 }

 // 소켓을 수동 대기모드로 세팅
 listen(server_fd, 5);
 // iterative  echo 서비스 수행
 while(1) {
  printf("Server : waiting connection request.\n");
  len = sizeof(client_addr);
  // 연결요청을 기다림
  client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &len);

  if(client_fd < 0) {
   printf("Server: accept failed.\n");
   exit(0);
  }
  printf("Server : A client connected.\n");
  
   // 블록되어 있다가 데이터가 오면 깨어남
   msg_size = recv(client_fd, buf, sizeof(buf), 0);
   buf[msg_size]='\0';

   printf("msg= %d\n",buf);
   printf("msg size= %d\n",msg_size);
   fopen_s(&pFile,"1.txt","w");
   fwrite(buf,3,3000,pFile);
   fclose(pFile);

  send(client_fd, temp_buf,BUF_LEN+1 , 0);
  closesocket(client_fd);
  // printf("%s",temp_buf); 
 }
 closesocket(server_fd);
 WSACleanup();  // Unload WinSock DLL
 return 0;
}

 

 

핸드폰 전화번호부를 추출해서 C서버로 보내는 기능을 하고 싶은데 처음엔 string형식으로 보낼 때는 잘 되었습니다.

하지만  저장시 착오가 생겨서 패킷에 헤더를 붙이고 C서버에 저장을 할려고 하니 계속 이상한 숫자가 전송이 되네요...

msg = 1989756895

msg size = 4

서버에서 이렇게 뜨네요.

어떤 곳에서 오류가 나는지 계속 고민해도 모르겠습니다.

 

고수님들 조언좀 부탁드릴게요!!