네트워킹
네트워킹은 인터넷에 연결되어 있는 원격지의 서버 또는 원격지의 단말과 통신해서 데이터를 주고받는 동작들을 포함한다. 네트워킹을 통해 단말의 데이터만 사용하는 것이 아닌 다른 위치의 서버나 다른 사람의 단말의 데이터를 조회할 수도 있다.
네트워크 연결방식은 2티어 C/S방식이 가장 간단한 방식이다. 클라이언트가 서버에 연결되어 데이터를 요청하고 응답받는 단순한 개념으로 쉽게 이해할 수 있다. HTTP, FTP, POP3 프로토콜 등의 연결방식은 모두 2티어로 서버에 접속하여 처리하는 것이다.
3티어 연결방식을 사용하면 서버를 더 유연하게 구성할 수 있다. 응용서버와 데이터 서버로 서버를 나눠 구성하면 DB를 분리할 수 있어 중간에 로직을 처리하는 응용서버가 더 다양한 역할을 할 수 있다는 장점이 생긴다. 단말간의 통신이 일반화되면서 클라이언트와 서버의 관계는 P2P모델로 변형되어 사용되기도 했다. P2P는 서버를 두지 않고 단말끼리 서버와 클라이언트의 역할을 수행하는 방식으로 파일 송수신이나 정보공유에 많이 쓰인다.
소켓
IP주소로 목적지 호스트를 찾고 포트로 통신 접속점을 찾아내는 소켓연결은 TCP와 UDP방식으로 나눌 수 있고 대부분 안전한 TCP 방식을 사용한다. HTTP프로토콜은 소켓으로 웹서버에 연결한 후 요청을 전송하고 응답받고나면 연결은 끊는다. 이 특성을 비연결성이라하는데 이런 특성때문에 실시간으로 데이터 처리하는 어플은 응답속도를 높이기 위해 연결성이 있는 소켓을 선호했었다. 하지만 인터넷의 속도가 빨라지면서 HTTP 를 사용하는 웹이 일반적이 되었고 웹서버로 많은 서버들이 만들어졌다. 아무튼 안드로이드는 소켓연결을 시도하거나 응답을 받아 처리할 때 스레드를 사용해야한다.
아래 코드는 UI인 텍스트뷰 접근을 위해선 핸들러를 사용하고 있다. 소켓서버는 serversocket 클래스로 만들고 클라이언트로부터 요청을 처리한다. while 구문을 사용해서 클라이언틑 접속을 기다리다가 클라이언트의 접속요청이 왔을때 accept를 통해 소켓 객체가 반환되므로 클라이언트 소켓 연결정보를 확인할 수 있다. 여기선 클라이언트에서 접속한 포트번호를 확인한 후 보낸 문자열에 from server 를 붙여서 클라이언트로 다시 보낸다. *인터넷을 이용해야하므로 manifest에 permission.INTERNET 추가해주기! 그리고 ObjectInputStream 은 자바객체정보를 편리하게 주고받도록 만들어진 것이라 자바아닌언어로 만들어진 서버랑 통신하면 데이터 송수신이 잘 안될수있어서 DataInputStream과 DataOutputStream을 잘 사용한다.
public class socket extends AppCompatActivity {
EditText editText;
TextView textView;
TextView textView2;
Handler handler = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_socket);
editText = findViewById(R.id.editTextTextPersonName);
textView = findViewById(R.id.textView9);
textView2 = findViewById(R.id.textView10);
Button button = findViewById(R.id.button17);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final String data = editText.getText().toString();
new Thread(new Runnable() {
@Override
public void run() {
send(data);
}
}).start();
}
});
Button button1 = findViewById(R.id.button18);
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new Thread(new Runnable() {
@Override
public void run() {
startServer();
}
}).start();
}
});
}
public void printClientLog(final String data){
Log.d("MainActivity", data);
handler.post(new Runnable() {
@Override
public void run() {
textView.append(data+"\n");
}
});
}
public void printServerLog(final String data){
Log.d("MainActivity", data);
handler.post(new Runnable() {
@Override
public void run() {
textView2.append(data+"\n");
}
});
}
public void send(String data){
try{
int portNumber = 5001;
Socket sock = new Socket("localhost", portNumber);
printClientLog("소켓연결함");
ObjectOutputStream outputStream = new ObjectOutputStream(sock.getOutputStream());
outputStream.writeObject(data);
outputStream.flush();
printClientLog("데이터전송");
ObjectInputStream inputStream = new ObjectInputStream(sock.getInputStream());
printClientLog("서버로부터 받음"+inputStream.readObject());
sock.close();
}catch (Exception ex){
ex.printStackTrace();
}
}
public void startServer(){
try{
int portNumber = 5001;
ServerSocket server = new ServerSocket(portNumber);
printServerLog("서버시작함 "+portNumber);
while(true){
Socket sock = server.accept();
InetAddress clientHost = sock.getLocalAddress();
int clientPort = sock.getPort();
printServerLog("클라이언트 연결함 "+clientHost+" : "+clientPort);
ObjectInputStream inputStream = new ObjectInputStream(sock.getInputStream());
Object obj = inputStream.readObject();
printServerLog("데이터받음 : "+obj);
ObjectOutputStream outputStream = new ObjectOutputStream(sock.getOutputStream());
outputStream.writeObject(obj + " from server");
outputStream.flush();
printServerLog("데이터보냄");
sock.close();
}
}catch (Exception ex){
ex.printStackTrace();
}
}
}
'안드로이드' 카테고리의 다른 글
데이터베이스 (0) | 2021.04.29 |
---|---|
웹 요청, Volley 사용, Json 다뤄보기 (0) | 2021.04.28 |
스레드와 핸들러 (1) | 2021.04.26 |
브로드캐스트 수신자 (0) | 2021.04.26 |
위험 권한 부여 (0) | 2021.04.23 |
댓글