일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- handler #looper #thread #runnable #핸들러 #루퍼 #스레드 #러너블
- 백준 #파이썬 #bfs #백트래킹 #1697 #숨바꼭질
- dfs #그래프 #graph #python #leetcode #course #schedule
- AsyncTask #doinbackground #스레드 #thread #android #안드로이드
- Python #leetcode #dfs #그래프 #백트래킹
- dfs #python #leetcode
- 파이썬 #zip
- dfs #leetcode #python #graph #그래프
- 리트코드 #팰린드롬 #파이썬
- dfs #python #leetcode #combination
- leetcode #subsets #dfs #itertools #python
- 다익스트라 #dijkstra #leetcode #파이썬 #python #algorithm #787
- 2004 #조합 0의 개수 #백준
- 다익스트라 #알고리즘 #bfs #그리디 #다이나믹프로그래밍 #leetcode #python
- dfs #bfs #트리구조 #이진트리 #leetcode #파이썬 #python
- dfs #bfs #트리구조 #이진트리 #leetcode #python #파이썬
- dfs #bfs #이진트리 #파이썬 #리트코드
- dfs #bfs #leetcode #python
- leetcode #python #dfs #재귀
- python #백준 #2580 #스도쿠 #dfs #백트래킹
- 코틀린 #Do it #깡샘 #안드로이드
- 해시테이블 #heapq #파이썬 #리트코드 #알고리즘
- dfs #이진트리 #트리구조 #직렬화 #역직렬화 #파이썬 #리트코드 #leetcode #python
- python #백준 #9375 #패션왕 #신해빈
- final #java #자바 #안드로이드
- gcd #최대공약수 #백준 #2981 #검문
- 아스테리스크 #Asterisk #파이썬
- dfs #leetcode #python
- context #android #getApplicationContext #activity #생명주기 #lifecycle
- exoplayer #mediaplayer #엑소플레이어 #안드로이드 #android
- Today
- Total
멋진 개발자가 되고 싶다
[Android] 안드로이드와 파이썬 서버간 TCP 통신하기 본문
http 서버에서 데이터(파일)를 받아와서 안드로이드에서 파일을 실행하는 과제를 하고 있다.
하지만 기본적으로 서버와 클라이언트의 개념도 몰랐기 때문에
이번 포스팅은 안드로이드폰에서 데이터를 보내면 서버에서 데이터를 받아다가 다시 안드로이드로 보내주는 내용이 될 것이다.
파이썬으로 서버를 돌리는 이유는
"간단한 코드로 되어 있어 구동이 제일 간편하기 때문"
python_server.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
import socket
host = ''
port = 9999
server_sock = socket.socket(socket.AF_INET)
server_sock.bind((host, port))
server_sock.listen(1)
while True:
print("기다리는 중")
client_sock, addr = server_sock.accept()
print('Connected by', addr)
data = client_sock.recv(1024)
data = data.decode()
print(data)
while True:
# 클라이언트에서 받을 문자열의 길이
data = client_sock.recv(4)
length = int.from_bytes(data, "little")
# 클라이언트에서 문자열 받기
msg = client_sock.recv(length)
# data를 더 이상 받을 수 없을 때
if len(data) <= 0:
break
msg = msg.decode()
print(msg)
msg = "eco: " + msg
data = msg.encode()
length = len(data)
# 클라이언트에 문자열 길이 보내기
client_sock.sendall(length.to_bytes(4, byteorder="little"))
# 클라이언트에 문자열 보내기
client_sock.sendall(data)
client_sock.close()
server_sock.close()
|
cs |
api 설명
socket.socket()
소켓 객체를 생성하는 함수
첫 번째 인자(family) : 주소 체계를 지정하는 인자로 socket.AF_INET = IP4v, socket.AF_INET6 = IP6v에 많이 쓰인다.
두 번째 인자(type) : 소켓의 타입으로 raw 소켓, stream 소켓, 데이터그램 소켓 등이 있다.
AF_INET과 SOCK_STREAM이 각각 디폴트로 지정되어 있다.
socket.bind()
클라이언트에서는 필요 없고 서버를 만들 때 필요한 메서드로튜플 형식을 받게 돼있다.
(ip address, port number)로 입력하면 되는데
ip address를 공백으로 입력하면 루프 백 주소로 자기 자신을 의미한다.
socket.listen()
서버가 데이터 수신을 기다리는 상태로
인자 값으로 들어가는 숫자는 해당 소켓이 몇 개의 동시접속을 허용할 것이냐는 의미이다.
socket.accept()
소켓에 누군가가 접속하여 연결되었을 때 결과 값이 튜플로 return 되는 함수다.
return 값은 새로운 소켓과 상대방의 AF(Address Family)를 전달한다.
이 이후부터의 데이터 송수신은 새로운 소켓을 이용한다.
socket.sendall(), socket.recv()
데이터를 송수신하는 메서드다.
여기서 몇 가지 주의해야 할 점은 클라이언트는 기존의 소켓으로 송수신을 하는 반면,
서버는 accpet()로 생성된 소켓으로 송수신을 한다는 것이다.
그리고 문자열을 전송할 때 encode()를 수행해 줘야 하는데,
이 encode() 메서드는 문자열을 byte로 변환해주는 메서드다.
파이썬 내부에서 생성된 문자열은 파이썬에서 생성된 객체이므로
전송 계층에 문자열을 그대로 보내면 에러가 발생한다.
물론 이 문자열을 읽어 출력할 때는 decode()를 사용해야 한다.
마지막으로 소켓은 턴 바이 턴 형식이기 때문에 데이터를 한 번 송신하면 다음은 수신을 해야 한다.
activity_main.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="40dp"
android:text="IP : "/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/editText"
android:textSize="40dp"/>
</LinearLayout>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="CONNECT"
android:id="@+id/button"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="+1"
android:id="@+id/plus_btn"/>
<Button
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="-1"
android:id="@+id/minus_btn"/>
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="25dp"
android:id="@+id/textView"/>
</LinearLayout>
|
cs |
위 코드를 적용하면 아래와 같이 표시된다.
MainActivity.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
|
package com.cookandroid.tcp_demo;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
public class MainActivity extends AppCompatActivity {
int sended_num=0;
boolean selected = false;
Button connect_btn;
Button plus_btn, minus_btn;
EditText ip_edit;
TextView show_text;
// about socket
private Handler mHandler;
private Socket socket;
private DataOutputStream outstream;
private DataInputStream instream;
private int port = 9999;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
connect_btn = (Button) findViewById(R.id.button);
connect_btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
connect();
}
});
plus_btn = (Button) findViewById(R.id.plus_btn);
plus_btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
selected = true;
sended_num += 1;
}
});
minus_btn = (Button) findViewById(R.id.minus_btn);
minus_btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
selected = true;
sended_num -= 1;
}
});
ip_edit = (EditText) findViewById(R.id.editText);
show_text = (TextView) findViewById(R.id.textView);
}
void connect(){
mHandler = new Handler(Looper.getMainLooper());
Log.w("connect","연결 하는중");
Thread checkUpdate = new Thread(){
public void run(){
// Get ip
String newip = String.valueOf(ip_edit.getText());
// Access server
try{
socket = new Socket(newip, port);
Log.w("서버 접속됨", "서버 접속됨");
}catch (IOException e1){
Log.w("서버 접속 못함", "서버 접속 못함");
e1.printStackTrace();
}
Log.w("edit 넘어가야 할 값 : ","안드로이드에서 서버로 연결 요청");
try{
outstream = new DataOutputStream(socket.getOutputStream());
instream = new DataInputStream(socket.getInputStream());
outstream.writeUTF("안드로이드에서 서버로 연결 요청");
}catch(IOException e){
e.printStackTrace();
Log.w("버퍼","버퍼 생성 잘못 됨");
}
Log.w("버퍼","버퍼 생성 잘 됨");
try{
while(true){
String msg = "java test message - ";
if (selected == true){
msg = msg + sended_num;
byte[] data = msg.getBytes();
ByteBuffer b1 = ByteBuffer.allocate(4);
b1.order(ByteOrder.LITTLE_ENDIAN);
b1.putInt(data.length);
outstream.write(b1.array(),0,4);
outstream.write(data);
data = new byte[4];
instream.read(data,0,4);
ByteBuffer b2 = ByteBuffer.wrap(data);
b2.order(ByteOrder.LITTLE_ENDIAN);
int length = b2.getInt();
data = new byte[length];
instream.read(data,0,length);
msg = new String(data,"UTF-8");
show_text.setText(msg);
selected = false;
}
}
}catch(Exception e){
}
}
};
checkUpdate.start();
}
}
|
cs |
connect() 함수를 만들어서 서버와 연결 및 thread 할당을 하도록 한다.
while 반복문을 통해 지속적으로 서버와의 데이터 송수신 상태를 유지한다.
'Android > 개발 관련 팁' 카테고리의 다른 글
[JAVA] final 이해하기 (0) | 2021.08.23 |
---|---|
[Android] getApplicationContext() 이해하기 (0) | 2021.08.02 |
[Android] Android에서 ExoPlayer 사용하기 (0) | 2021.07.19 |
[네트워크] TCP 통신이란? (0) | 2021.07.15 |
[Python] http 및 https 서버 구축하기 (0) | 2021.07.15 |