[JAVA] Socket 서버 구현시 안전하게 SocketServer를 종료하는 방법

프로그래밍 팁 2015. 10. 14. 23:18

 안드로이드를 활용한 다양한 소켓 프로그래밍들의 에제를 둘러보다 보면 Server 측의 Socket을 다루는 데 종종 난해한 경우가 있습니다. 가령 Client측으로부터 Socket 통신이 한창 진행중인 상황에서 서버측 Socket을 닫아버리면 진행중이던 통신 관련 작업이 모두 끝나기도 전에 서버가 종료되어 버리는 심각한 상황이 발생할 수도 있는 것이지요.


 본 포스팅에서는 Java를 활용한 서버측의 Socket을 좀 더 안정적으로 종료시키는 방법에 대해 알아보도록 하겠습니다.


- Client와 Socket 통신이 진행중인 상황에서 ServerSocket이 강제로 종료되지 않도록 하기 위해 synchronized를 사용합니다. 이는 C/C++에서 제공하는 Mutex와 유사한 역할을 합니다. synchronized() 의 인자(Argument)를 가지고 있는 쪽에서 실행을 하다가 종료가 되었을 때 이를 다른 쪽에서 점유한 후 실행이 종료될 때 까지 다른 부분에서는 실행되지 않도록 설정합니다.


- ServerSocket이 accpt()를 실행하던 중에 종료되었을 때 SocketException이 발생합니다. 이 때 try-catch를 통해 해당 Exception을 catch한 후 Server가 안전하게 종료되었음을 확인합니다.


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
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
 
public class Main {
 
    public static void main(String[] args) {
        // TODO Auto-generated method stub
 
        RecvMessage rm = new RecvMessage();
        //Server Thread를 실행합니다.
        rm.start();
 
        ....
 
        //ServerSocket를 닫음으로서 Server Thread를 종료합니다.
        rm.closeServer();
 
    }
 
    static class RecvMessage extends Thread {
        boolean ready = true;
        Socket socket;
        InputStream is;
        ObjectInputStream ois;
        String clientIp;
        ServerSocket sockserver;
 
        //Mutex로 사용할 Object 변수를 선언합니다.
        Object lock = new Object();
 
        public void closeServer() {
            try {
                //Client와 Socket 통신이 진행중일 경우 종료될 때까지 기다립니다.
                synchronized (lock) {
                    sockserver.close();
                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
 
        public void run() {
            try {
                sockserver = new ServerSocket(8200);
                while (ready) {
                    socket = sockserver.accept();
                    //Client와의 통신이 종료될 때 까지 SocketServer의 종료를 보류시킵니다.
                    synchronized (lock) {
                        is = socket.getInputStream();
                        ois = new ObjectInputStream(is);
 
                        clientIp = (String) ois.readObject();
 
                        System.out.println("Client IP : " + clientIp);
                        ois.close();
                        is.close();
                        socket.close();
                    }
                }
 
            } catch (SocketException e) {
                //ServerSocket가 종료되었을 때 실행됩니다.
                System.out.println("ServerSocket is closed!");
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
 
}
 
 
cs


300x250

[컴퓨터비전]이미지 변환시 DoF(Degrees of Freedom)에 대한 고찰

공대생의 팁 2015. 10. 13. 00:13

 영상처리와 컴퓨터비전 분야에서 가장 중요한 요소로 Matrix 변환을 기반으로 하는 선형대수(Linear Algebra)가 있습니다. 특히 화면에 나타나는 이미지를 변환할 때 (Geometric Transformations를 하기 위해 사용되는 행렬), DoF라는 개념이 언급됩니다. 본 포스팅에서는 이 DoF에 대해 이야기해 보려 합니다.


-DoF(Degrees of Freedom)란?

 DoF(Degrees of Freedom), 우리말로 '자유도'라 일컫는 요소로 이미지가 변환이 될 때 최소한으로 필요로 하는 독립변수의 수라고 정의할 수 있습니다. 이에 대해 각 Geometric Transformations들을 통해 알아보도록 하겠습니다.


-Translation


 이미지 변환중 가장 단순하다고 할 수 있는 변환 중 하나입니다. 이를 Matrix로 나타내면 다음과 같습니다.


위의 식에서 보이는 바와 같이 총 2개의 변수에 의해 이미지가 변환되고 있는 것을 알 수 있습니다. 각 변수는 이미지의 x축과 y축을 이동하는 식으로서 이는 Translation의 DoF가 2임을 알 수 있습니다.

 또한 Translation의 결과물은 원본 이미지에서 큰 변화가 일어나지 않습니다.


-Rigid(Euclidean)

위에서 보았던 Translation을 수행한 후 이미지를 일정 각도로 회전시킨 결과입니다. 이를 Matrix로 나타내면 다음과 같습니다.


위의 식에서 보는 바와 같이 x축으로의 이동, y축으로의 이동, 회전각도 Θ로 DoF는 3임을 알 수 있습니다.

 위 Rigid의 최종 결과물은 원본 이미지의 높이 및 너비와 같은 길이가 보존되는 것을 알 수 있습니다.


-Similiary

위의 Rigid Transform에서 결과물의 사진 크기가 변하였음을 확인할 수 있습니다. 이를 Matrix로 나타내면 다음과 같습니다.


 위의 식에서 보는 바와 같이 x축으로의 이동, y축으로의 이동, 회전각Θ, 크기변수s 로 DoF는 4임을 알 수 있습니다.

 위 Similary의 최종 결과물은 원본 이미지의 직각 부분이 유지되는 것을 알 수 있습니다.


-Affine

원본 이미지에 Affine Matrix가 적용되면 이미지가 위에서 보는 바와 같이 일그러진 모습을 하고 있는 것을 보실 수 있습니다. 이를 Matrix로 나타내면 다음과 같습니다.


Affine Matrix의 DoF는 6임을 확인하실 수 있습니다.

 위 Affine의 최종 결과물은 원본 이미지의 두 변의 평행이 보존됨을 확인하실 수 있습니다.


-Projective

 원본이미지에 Projectiive가 젹용되면 마치 이미지가 정사영에 투영된 듯이 이미지를 기울여서 보는 듯한 느낌이 들 겁니다. 이를 Matirx로 나타내면 다음과 같습니다.


Projective Matrix의 DoF는 8임을 알 수 있습니다.

 위 Projective의 최종 결과물은 원본 이미지의 특정 두 변의 평행이 유지되는 것을 알 수 있습니다.

300x250

Error: The SDK Build Tools revision is too low for project

 Eclipse에서 사용하던 프로젝트를 Android Studio로 가져왔을 때 아래와 같은 상황의 에러가 발생하였습니다.


Error: The SDK Build Tools revision (19.0.0) is too low for project. Minimum required is 19.1.0


 위 에러는 프로젝트가 기존 Eclipse에서 사용하던 Build Tools가 Android Studio에 설치된 Build Tools보다 버전이 낮아 발생하는 에러 입니다. 위 에러를 해결하기 위해서는 아래와 같은 과정을 수행합니다.


1.에러가 발생한 프로젝트의 폴더 -> build.grade 를 실행합니다.

2.android 부분에서 BuildToolsVersion 부분을 최소 요구 버전으로 설정합니다. 본 예제의 경우 버전을 19.1.0으로 수정합니다.



 위와 같이 적용한 후 Android Studio를 종료한 후 다시 실행하면 제대로 적용되어 있는 것을 확인하실 수 있습니다.




300x250