한 디바이스에 서버앱 / 클라이언트앱을 만들어서 통신하려고 하고 있습니다.
PC 서버 / 안드로이드 클라이언트 예제를 이용해서
안드로이드에서 서버앱 / 클라이언트앱 만드는 것 까지 구현을 했습니다.
하지만 예제가 서버는 데이터를 받는 기능만 되어 있는 소스여서 서버에서도 클라이언트로 전송이 가능하게끔 수정하는 중입니다.
그런데 실행해보는 도중에 클라이언트앱에서 버튼을 누르면 메시지가 전송이 되어야 하는데, 널포인트 에러가 나버리네요..
워낙 초보라 문제점을 찾고 있지 못해서 소스 올려봅니다...
서버 앱
package choi.test.server;public class ServerApp extends Activity implements Runnable{
public static TextView chatting; public static EditText inText; public static Button sendBtn; public static ServerSocket server; public static Socket client; public static String str = ""; public static Thread ServerThread; public static PrintWriter out; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main);
chatting = (TextView) findViewById(R.id.chatText); inText = (EditText) findViewById(R.id.inText); sendBtn = (Button) findViewById(R.id.send);
ServerThread = new Thread(new ServerApp()); ServerThread.start(); sendBtn.setOnClickListener(new OnClickListener() { // 전송 버튼 public void onClick(View v) { String it = inText.getText().toString(); out.println(it); } }); }
public void run() { setServer(); process(); } public void setServer(){ try { server = new ServerSocket(8088);// ServerSocket 객체 생성, 포트8088 } catch (IOException e) { e.printStackTrace(); } } public void process(){ while (true) { try { client = server.accept(); BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream())); str = in.readLine(); out = new PrintWriter(new BufferedWriter( new OutputStreamWriter(client.getOutputStream())), true); // out.println("Server Received " + str); chatting.setText("클라이언트 : " + str); } catch (Exception e) { e.printStackTrace(); } } } }
클라이언트 앱
public class ClientApp extends Activity implements Runnable{ public static Button sendBtn; public static Socket cSocket; public static String str = ""; public static EditText inText; public static TextView chatting; public static PrintWriter out; public static BufferedReader in; public static Thread ClientThread; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); chatting = (TextView) findViewById(R.id.chatText); inText = (EditText) findViewById(R.id.inText); sendBtn = (Button) findViewById(R.id.send); ClientThread = new Thread(new ClientApp()); ClientThread.start(); sendBtn.setOnClickListener(new OnClickListener() { // 전송 버튼 public void onClick(View v) { String it = inText.getText().toString(); out.println(it); // 널포인트 에러가 나는 부분 } }); }
public void run() { try{
String serverIP = InetAddress.getLocalHost().getHostAddress(); InetAddress serverAddr = InetAddress.getByName(serverIP); cSocket = new Socket(serverAddr, 8088);//Socket 객체 생성 8088포트로 연결 in = new BufferedReader(new InputStreamReader(cSocket.getInputStream()));//input스트림 가져오기 out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(cSocket.getOutputStream())), true); while (true) { str = in.readLine();// input스트림에서 데이터 읽어오기
chatting.setText("서버 : " + str); } }catch(IOException e){ } } }
아. 그리고... 휴대폰에서 계속 테스트를 하는데 폰이 뜨거워져서 봤더니 램을 많이 잡아먹고 있더라구요.
이건 쓰레드 때문인건가요? 앱을 실행했다가 백버튼으로 나가도 쓰레드가 돌고 있는건가요?
일단 답변 감사합니다.
그 널포인트 에러 나는 것이 id가 없어서는 아니고.. out 객체가 없다고 나오는 것 같습니다.
근데 소스에 보면 run()안에 out 객체를 생성했는데 왜 없다고 하는지 잘 모르겠습니다..
그리고 while문에 true 한 것은 InputStream을 계속 아와야 하는것 같아서 그렇게 한건데..
잘못 된 건가요...
제가 짜려고 하는 것이.. 소켓을 생성하고 연결이 되면 InputStream은 while문 계속 돌면서 데이터가 수신 될 경우 뿌려주고
OutputStream으로 메시지를 보내고 싶을 때 마다 보내면 된다고 생각하고 짜려고 하고 있는데.. 굉장히 어려운 것 같습니다.
많은 조언 부탁드리겠습니다...
클라이언트쪽에서 우선 소켓이 안열린게 아닐까요?
서버 클라이언트 모두 하나의 시스템에서 돌리시나요?
하나로 돌린다면야 상관없지만 아니면 아래 부분에서 문제가 생깁니다. 서버 아이피를 직접 넣어주세요.
InetAddress.getLocalHost().getHostAddress();호출하시면 아마도 127.0.0.0일듯 싶습니다.
제대로 소켓부터 열리는지 확인을 해야 할것 같아요.
일단 out에서 에러나는 이유가 소켓 연결이 안되는 경우 catch문으로 빠져 생성이 안될 소지가 있습니다.
catch 문에 로그를 찍어 보시는게 좋아 보이고요.
while 문에 flag를 달라고 한 이유는 Thread는 중지되지 않습니다.
back키로 나오더라도 Thread는 계속 돌고있죠.
실행 -> Thread 동작 1. -> app 종료 -> 실행 -> Thread 동작 2. -> app 종료.
이런식으로 Thread는 계속 돌고있습니다. onPause나 onDestory에서 thread의 flag를 false로 변경해 줘야 무한 룹에서 벗어 날 수 있습니다.
Thread는 run 후 정지 시키지 않으면 계속 돌아요.
Activity의 life cycle과 무관합니다. Thread는 Thread니까요.
public
void
process(){
14.
while
(
true
) {
true 대신 flag하나 사용하시면 해결 될거 같고.
그리고 모든 객체를 public static으로 사용하셨는데... 좀 안좋은 방법입니다.
오류 부분은
1. main xml에 . R.id.inText 아이디의 EditText가 없을 가능성이 크다고 생각합니다.
-- 서버 클라이언트 둘다 같은 layout을 사용하는데 서버 사용시는 문제 없고 클라이언트만 문제가 있는건가요?
2. inText 에 아무 내용이 없다.
3. 프로젝트를 클린하고 새로 빌드. 가끔 xml의 수정사항이 반영안될 때가 있습니다.