먼저
----------------------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
서버에서 이렇게 뜨네요.
어떤 곳에서 오류가 나는지 계속 고민해도 모르겠습니다.
고수님들 조언좀 부탁드릴게요!!