0. 시작하기

 

1. 함수 오버로딩 ( CPP/F_Overloading.cpp )

C++도 다른언어와 마찬가지로 함수와 함수 오버로딩을 제공합니다.

 

오버로딩을 구현하기 위해서의 필수 조건은 동일한 함수명이라 하더라도, 입력하는 인자의 값에 따라 수행할 함수를 구분할 수 있어야합니다.

 

예제를 보면 쉽게 이해가 가능합니다.

 

#include <iostream>

int func(int num){
    return num;
}

int func(int num1, int num2){
    return num1 + num2;
}

int main(void){
    std::cout << func(10) << std::endl;
    std::cout << func(10, 10) << std::endl;

    return 0;
}

실행결과

 

보통의 경우 유사한 기능을 하는 함수에 동일한 이름을 주어 함수 오버로딩을 구현합니다.

0. 시작하기

 

1. 확장자

기존 C++은 확장자로 '---.c'를 사용하였습니다. 하지만, C++에서는 '---.cpp'이라는 확장자를 사용합니다.

일반적으로 IDE가 확장자에 따라서 적용하는 컴파일러를 결정하는 경우가 많기 때문에 C++ 사용시 꼭 cpp확장자를 사용해야합니다.

 

헤더파일의 경우 C와 마찬가지로 '---.h' 형태의 확장자를 사용합니다. 다만, 코드에서 헤더파일을 선언할 때, 기존 C에서는 <stdio.h>의 형태로 [파일명+확장자]형태로 선언했다면, C++에서는 <iostream> 이라는 파일명으로 선언을 합니다.

 

 

 

2. 기본 입출력 ( CPP/iostream.cpp )

기본 입출력은 <iostream> 헤더를 사용합니다.

 

샘플 코드는 아래와 같습니다.

 

#include <iostream>

int main(void){
    int temp = 0;
    std::cout << "Console Out" << std::endl;
    std::cout << "Hello" << "World~!" << std::endl;

    int a, b;
    std::cout << "숫자 2개입력 > ";
    std::cin >> a >> b ;
    std::cout << a+b << std::endl;
    return 0;
}

실행결과

 

 

 

3. 배열 입출력시 주의사항 ( CPP/iostream_arry.cpp )

배열을 이용해서 단어나 문자를 입력하는 경우가 많이 있습니다.

 

아래 코드를 보고 한눈에 잘못된 부분을 찾으셨다면 '짝짝짝~'

#include <iostream>

int main(void){
    char str[100] = "배열 입출력 주의점";
    std::cout << "str 값 : " << str << std::endl;

    char temp[100];
    std::cout << "값 입력 > ";
    std::cin >> temp;  // "test test test" 를 입력할 예정
    std::cout << "입력한 값 출력 : " << temp << std::endl;
    
    
    return 0;
}

 

위의 코드에서 문제인 부분은 [입력] 부분입니다.

 

temp에 "test test test"를 입력할 경우 [std::cin]은 스페이스바를 기준으로 입력값을 정하기 때문에 처음 'test'만 temp값에 저장되고 나머지 'test test'는 버퍼에 남게됩니다.

 

실행결과

 

때문에 char 배열에 cin을 이용해서 값을 지정할 경우 공백이 없는 문자열을 이용하던가 혹은 위의 문제를 해결할 코드를 사용해야합니다.

WOL 기능에서 사용되는 매직패킷을 전송하는 프로그램

python + pyqt

 

0. 개발환경

  • 맥북 OSX
  • PyCharm (Python 3.7x) + pyqt

1. GUI

 

먼저 대략적인 앱 디자인을 구성합니다.

저는 위와같이 대충 만들었습니다.

정확한 크기는 코딩단계에서 조절해줍니다.

 

[QT 디자이너]를 사용하지 않을 예정이기 때문에 대충 목표디자인을 파워포인트로 잡았습니다.

 

 

 

 

2. Coding

udp통신이고 기존에 파이썬으로 WOL패킷전송을 수행하는 코드를 작성해둔 적이 있었기 때문에 해당코드를 그대로 이용했습니다.

 

2019/05/14 - [이론/네트워크] - [네트워크 패킷] Python으로 WOL패킷 송신하기(1/2)

2019/05/14 - [이론/네트워크] - [네트워크 패킷] Python으로 WOL패킷 송신하기(2/2)

 

 

import sys
import socket, struct, time
from PyQt5.QtWidgets import *
from PyQt5.QtGui import QPixmap, QIcon
from PyQt5.QtCore import Qt

class LayoutWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        wg = WidgetSet()
        self.setCentralWidget(wg)
        self.statusBar().showMessage('Youngq.tistory.com')

        self.setWindowTitle('WOL Program')
        self.setWindowIcon(QIcon('web.png'))
        self.setGeometry(500, 500, 350, 180)
        self.show()

class WidgetSet(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        # Line 1 : Wol 이미지 + msg 영역
        hbox0 = QHBoxLayout()
        hbox0.setAlignment(Qt.AlignVCenter)

        pixmap = QPixmap('wol_mini.png')
        pixmap = pixmap.scaledToWidth(35)
        lbl_img = QLabel()
        lbl_img.setPixmap(pixmap)
        hbox0.addWidget(lbl_img)
        hbox0.addStretch(200)

        msg = QLabel()
        msg.setFixedSize(200,25)
        msg.setText("Ready")
        msg.setAlignment(Qt.AlignRight)
        self.err = msg
        hbox0.addWidget(msg)

        # Line 2 : 대역폭입력 + 콤보박스
        hbox1 = QHBoxLayout()
        hbox1.setAlignment(Qt.AlignVCenter)

        qle1 = QLineEdit(self)
        qle1.setFixedSize(170, 25)
        qle1.setPlaceholderText("목적지 IP주소 또는 망주소 입력")
        self.ip = qle1
        hbox1.addWidget(qle1)
        hbox1.addStretch(20)

        cIP = QLabel()
        cIP.setFixedSize(110, 30)
        currentIP = self.ipaddr()
        cIP.setText("IP : "+currentIP)
        hbox1.addWidget(cIP)

        # Line 3 : 맥주소 입력 + 전송버튼
        hbox2 = QHBoxLayout()
        hbox2.setAlignment(Qt.AlignHorizontal_Mask)
        qle2 = QLineEdit(self)
        qle2.setFixedSize(170, 25)
        qle2.setPlaceholderText("MAC 주소 입력")
        self.mac = qle2
        hbox2.addWidget(qle2)
        hbox2.addStretch(20)

        btn = QPushButton(self)
        btn.setText('Send')
        btn.setFixedSize(70, 30)
        self.sendBtn = btn
        btn.clicked.connect(self.sending) # EventH

        hbox2.addWidget(btn)
        # Stacking : 레이아웃 배치
        vbox = QVBoxLayout()
        vbox.addLayout(hbox0)
        vbox.addLayout(hbox1)
        vbox.addLayout(hbox2)
        self.setLayout(vbox)

    def sending(self):
        try:
            WOL(self.mac.text(), self.ip.text())
            self.err.setText("신호 전송완료")
        except:
            self.err.setText("잘못된 입력이 존재합니다.")

    def ipaddr(self):
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s.connect(("8.8.8.8", 80))
        return s.getsockname()[0]

def WOL(macAddr, network):
    sep = macAddr[2]
    macAddr = macAddr.replace(sep, '')

    data = b'FFFFFFFFFFFF' + (macAddr * 16).encode()
    send_data = b''

    for i in range(0, len(data), 2):
        send_data += struct.pack('B', int(data[i: i + 2], 16))

    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
    for i in range(3):
        sock.sendto(send_data, (network, 9))
        time.sleep(0.05)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = LayoutWindow()
    sys.exit(app.exec_())

 

특별한 알고리즘이 필요없는 단순 프로그램이지만, GUI 구성까지 포함해서 100줄 조금 넘어가는 코드로... 역시 파이썬입니다...

 

해당 코드는 다음 링크에서 복사 가능합니다.

 

https://github.com/yekyu94/WOL_python/blob/master/wol.py

 

yekyu94/WOL_python

python WOL GUI Coding. Contribute to yekyu94/WOL_python development by creating an account on GitHub.

github.com

 

Pyqt를 통해서 제작한 코드이기 때문에 pyqt가 설치되어있지 않는 경우 애러가 발생합니다.

 

 

 

 

3. Testing

 

 

실행화면
와이어샤크로 확인

 

위와같이 전송이 완료되면 입력한 IP주소와 MAC주소를 타겟으로한 WOL패킷이 3개 전송되는 것을 볼 수 있습니다.

 

이렇게 만든 프로그램을 pyinstaller같은 라이브러리를 이용하여 쉽게 exe파일등으로 변환이 가능합니다.

 

해당부분은 넘어가겠습니다.

0. 정의

  • 그래프(G)는 정점(Vertex)와 간선(Edge)로 이루어집니다.   * G = (V, E)
  • 인접(Adjacent) : 간선(Edge)으로 연결된 두 정접(Vertex)
  • 완전그래프(Complete Graph) : 간선(Edge)의 개수가 최대인 그래프
  • 경로(Path) : 경로의 길이는 경로사이의 간선(Edge)의 수
  • Directed Graph : 방향성이 있는 간선(Edge)을 갖는 그래프
  • Undirected Graph : 방향성이 없는 간선(Edge)을 갖는 그래프

 

그래프는 아래와 같이 표현합니다.

그래프 예제

 

표를 이용한 그래프 표현

 

 

1. Graph Traversal

그래프의 탐색방법은 크게 두가지로 나눠집니다.

 

  • Depth First Search(DFS) : 깊이 우선 탐색
  • Breadth First Search(BFS) : 너비 우선 탐색

두 개념은 그래프와 트리와 같이 Vertex와 Edge로 이루어진 자료구조에서 사용되는 탐색방법입니다.

 

두개의 차이는 아래를 참고하면 쉽게 이해할 수 있습니다.

 

출처 : http://blog.hackerearth.com/wp-content/uploads/2015/05/dfsbfs_animation_final.gif

 

DFS는 순환호출 형태로 많이 구현하며 BFS는 Quere를 이용하여 쉽게 구현할 수 있습니다.

 

void DFS(Vertex* V)
{
	Edge* E = NULL;
    printf("%d ", V->Data);
    
    V->Visited = Visited;
    
    E = V->AdjacencyList;
    
    while(E != NULL){
    	if( E->Target != NULL && E->Target->Visited == NotVisited )
        	DFS( E-> Target );
        
        E = E->Nest;
    }
}
       

전체 알고리즘자료는 깃헙에 올리고있습니다. => https://github.com/yekyu94

 

yekyu94 - Overview

네트워크 프로그래밍 / 텐서플로우 / 보안 / 고양이. yekyu94 has 15 repositories available. Follow their code on GitHub.

github.com

 

 

1. DNS Query Message

DNS는 UDP 53번 포트를 사용합니다.

 

DNS Packet

Google.com에 접속했을 때 위와같은 DNS query와 DNS response가 전송되는 것을 볼 수 있습니다.

 

먼저 DNS Query Message를 확인해보면 아래와 같은 것을 볼 수 있습니다.

 

DNS Query Message

위의 붉게 표시한 부분이 DNS Header에 해당하는 부분입니다.

 

DNS message Header는 기본적으로 [트랜잭션 ID, flag, Question count, Answer count, Name server count, Additional Recode count]를 갖고 있습니다.

 

현재 해당 Packet의 DNS Message 는 아래와 같습니다.

 

Transaction ID = 0b 8e

Flags = 0100

Questions = 1

Answer = 0

Authority RRs = 0

Additional RRS = 0

Queries = www.google.com

 

 

2. Query Flag

트랜잭션 ID는 매 Query에 대한 식별 ID이며, Flags 0x0100은 아래와 같이 맵핑됩니다.

QR

Opcode

AA

TC

RD

RA

000

rCode

0

0000

0

0

1

0

000

0000

 

  • OR 0 : 이 메시지가 Query 라는 의미
  • Opcode 0000 : 표준 질의 또는 표준 질의에 대한 응답
  • AA 0 : 네임서버 권한이 인정 X
  • TC 0 : 응답메시지가 512 바이트 이하
  • RD 1 : 응답 형태가 Recursive인지 Iterative인지 정해주는 것으로 여기서 1은 Recursive 응답을 요구한다는 의미
  • RA 0 : 네임서버가 Recursive 질의가 가능한지 나타내며
  • rCode : 0 = No Error (1 = Format Error, 2 = ServFail, 3 = DNS존재 X)

 

3. DNS Response Message

DNS Response Message

 

마찬가지로 해당 패킷의 Response Message는 아래와 같은 내용을 갖고있습니다.

Transaction ID = 0b 8e

Flags = 81 80

Questions = 1

Answer = 6

Authority RRs = 4

Additional RRS = 8

Queries = www.google.com

Answers = 

www.google.com addr 108.177.97.104

www.google.com addr 108.177.97.105

www.google.com addr 108.177.97.147

www.google.com addr 108.177.97.99

www.google.com addr 108.177.97.103

www.google.com addr 108.177.97.106

Authoritative Nameservers =

google.com ns ns4.Google.com

google.com ns ns1.Google.com

google.com ns ns2.Google.com

google.com ns ns3.Google.com

Additional records =

ns1.google.com addr 216.239.32.10

ns2.google.com addr 216.239.34.10

ns3.google.com addr 216.239.36.10

ns4.google.com addr 216.239.38.10

ns1.google.com addr 2001:4860:4802:32::a

ns2.google.com addr 2001:4860:4802:34::a

ns3.google.com addr 2001:4860:4802:36::a

ns4.google.com addr 2001:4860:4802:38::a

 

 

4. Response Flag

이 Packet의 Transaction ID는 Query의 Transaction ID와 동일하며, Flags는 아래와 같이 매핑됩니다.

QR

Opcode

AA

TC

RD

RA

000

rCode

1

0000

0

0

1

1

000

0000

 

  • OR 1 : 이 메시지가 response 라는 의미
  • Opcode 0000 : 표준 질의 또는 표준 질의에 대한 응답
  • AA 0 : 네임서버 권한이 인정 X
  • TC 0 : 응답메시지가 512 바이트 이하
  • RD 1 : 응답 형태가 Recursive인지 Iterative인지 정해주는 것으로 여기서 1은 Recursive 응답을 요구한다는 의미
  • RA 1 : 네임서버가 Recursive 질의가 가능한지 나타내며
  • rCode : 0 = No Error (1 = Format Error, 2 = ServFail, 3 = DNS존재 X) 

이 응답 메시지로부터 client는 www.google.com이라는 사이트의 address와 Google.com의 네임서버를 얻어올 수 있습니다.

0. 시작하기

  • 와이어샤크 프로그램을 통한 HTTP Handshake 과정을 다룹니다.
  • 와이어샤크 프로그램에 대한 설명은 제외합니다.
  • 맥(OSX)환경에서 실습 및 작성되었습니다.

1. TCP 통신 과정

 

기본적인 TCP 통신과정을 그려보면 아래와 같습니다.

 

TCP 통신

[연결] - [데이터 통신] - [종료] 의 3단계로 진행되며 이제부터는 HTTP 통신을 예제로하여 해당 과정을 살펴보겠습니다.

 

그전에 앞서 각 과정에서 전송되는 패킷의 구조와 Flag들이 의미하는 것은 아래와 같습니다.

 

출처 : http://www.ktword.co.kr/abbr_view.php?m_temp1=2437

 

  • URG(긴급 데이터 표시) : 상위계층에서 긴급데이터임을 표시한 패킷으로 전송시 우선적으로 전송됨
  • ACK(응답확인) : 패킷을 정상적으로 수신했다는 것을 알리기위한 패킷
  • PSH(즉시 확인 요청) : 해당 표시가된 패킷은 수신한 경우 버퍼가 차는 것을 기다리지 않고 즉시 상위계층으로 전달
  • RST(연결 초기화 요청) : TCP 연결상 문제가 발생시 현재 연결을 끊고 다시 연결할 것을 요청함
  • SYN(회선 연결 요청) : TCP 연결을 요청하는 패킷이며, 현재 자신의 준비상태를 상대방에게 전달
  • FIN(회선 연결 종료) : 모든 데이터 전송이 완료되었음으로 연결을 종료할 것을 알림

 

 

2. HTTP Connect - 연결과정

 

연결과정

HTTP 는 TCP 80번 포트를 이용합니다. (HTTPS 는 443번)

 

테스트할 사이트는 통계청 사이트(http://kostat.go.kr)입니다. 통계청 사이트가 https를 사용하지 않고 있어서 선정했습니다.

 

아래는 통계청 사이트에 접속할때 교환되는 패킷 내용입니다.

 

Packet Chapture 시작부분

내 PC : Youngui-MacBook-Pro

통계청 : 125.60.43.187

 

 

3 Way Handshake

처음 3줄을 보면 위와깉이 SYN, SYN ACK, ACK가 전송되는 것을 볼 수 있습니다.

 

연결과정은 위와같은 3개의 패킷이 핵심입니다.

 

  • SYN (클라이언트 -> 서버) : 클라이언트가 서버에 TCP연결을 요청합니다. 이때 자신의 연결준비 상태를 함께 전송합니다.
  • SYN + ACK (서버 -> 클라이언트) : 서버가 클라이언트의 연결 요청에 응답(ACK)하며, 자신의 연결 준비상태를 알립니다.(SYN)
  • ACK (클라이언트 -> 서버) : 클라이언트가 서버의 연결준비 상태(SYN)를 포함한 패킷을 잘 수신했다고 알립니다.(ACK)

위의 단계를 3 Way-Handshake라고 부릅니다. 정상적으로 완료가 될 경우 이후부터 데이터 전송이 가능합니다.

 

 

 

3. HTTP Data Transmission - 데이터 통신

데이터 통신

여기서는 HTTP 프로토콜을 이용하여 TCP 전송에 대해서 다루기 때문에 전송되는 데이터는 [HTTP 프로토콜]에서 사용하는 메서드와 해당 메서스에 대한 응답등이 해당됩니다.

 

 

데이터 전송

위의 3개의 패킷은 TCP Connect 이후 최초의 데이터 패킷입니다. 각 패킷은 아래와 같은 역할을 합니다.

 

  • HTTP (클라이언트 -> 서버) : 기본 url(kostat.go.kr) /(최상위) 위치에 대한 html파일을 요청합니다. 즉, kostat.go.kr에 접속했을때 최초로 보여줄 html파일에 대한 정보를 서버에 요청하는 과정입니다.
  • HTTP 200 OK (서버 -> 클라이언트) : 200번 응답은 정상적으로 요청한 내용을 전송했다는 의미이며, 위에서 요청한 kostat.go.kr/ 에 접속시 보여줄 html파일을 전송했다는 의미입니다.
  • ACK (클라이언트 -> 서버) : 서버가 클라이언트에게 전송한 html파일을 정상적으로 수신했다는 ACK응답입니다.

 

데이터 통신과정에서 발생하는 대부분의 통신내용은 위와같은 방식을 갖고있습니다.

 

물론 데이터의 크기가 MTU(최대전송단우) 이상일 경우 단편화(Fragmentation)를 통해서 데이터를 조각내서 정송하게 됩니다.

 

아래는 단편화된 패킷의 예제입니다.

단편화 예제

kostat.go.kr/protal/kor_nw/1/1/index.board?bmode=read&Seq=376435 에 대한 GET요청에 대해서 서버는 응답을 여러개로 나눠서 보내는 것을 볼 수 있습니다.

 

이에따라 클라이언트도 여러개의 ACK를 생성해 전송하게 됩니다. (PDU = 프로토콜 데이터 유닛)

 

여기서 전송되는 데이터의 최대크기가 1514 Byte인 것을 볼 수 있습니다. 이를통해 1514 Byte가 일반적인 이더넷 패킷의 MTU가 된다는 것을 알 수 있습니다.

 

 

 

 

4. HTTP Disconnect - 연결종료

 

 

4 Way-HandShake

위와같은 전송이 TCP의 연결종료에 해당합니다.

 

하지만, 항상 위와같은 상태는 아닐 수 있습니다. FIN메시지는 데이터 전송이 완료되었다고 서버가 판단하고 먼저 보낼 수도 있습니다.

 

연결종료

 

  • FIN + ACK (클라이언트 -> 서버) : 이전에 서버로부터 받은 데이터를 잘 수신하였으며(ACK), 모든 데이터 전송이 끝났음으로 연결종료를 요청합니다.(FIN)
  • FIN + ACK (서버 -> 클라이언트) : 서버가 정상적으로 FIN 메시지를 수신하였으며(ACK), 서버는 더 이상 처리할 데이터가 없음으로 마찬가지로 즉시 FIN메시지를 전송합니다.(만약 더 통신할 데이터가 있을 경우 ACK만 전송할 후 데이터 교환 후 FIN 메시지를 보냅니다.)
  • ACK (클라이언트 -> 서버) : 서버의 FIN 메시지를 정상적으로 수신했음을 알립니다.

 

위의 모든 과정이 끝나면 서버와 클라이언트 모두 연결을 위해 할당했던 리소스를 회수합니다.

  1. 뒹굴뒹굴 YoungQ 2019.07.24 15:52 신고

    중간에 Source Port가 변경되는 부분은 이미지가 깨져서 와이어샤크로 다시 캡처하다보니 발생한 문제로 모두 동일한 Port라고 봐도 무관합니다.

  2. 2020.07.15 20:51

    비밀댓글입니다

0. Intro to Google Colab

 

Colab은 구글이 왜 구글인지를 알려주는 멋진 녀석입니다.

머신러닝을 처음 입문할 때 첫 난관은 다름이 아니라 개발환경을 구축하는 것입니다.

 

어마어마한 하드웨어의 가격은 물론이며, Cuda와 같이 생소한 녀석들과 다양한 파이썬 라이브러리들을 만나야 하죠.

 

Colab은 이러한 문제를 해결해주었습니다. "주피터 노트북"을 사용해보신 분들이라면 Colab에 접속하는 순간 친근한 느낌을 받을 수 있으실 겁니다. 왜냐하면 주피터 개발진들이 참여하여 만든거니까요~ ㅎㅎ

 

1. Colab 시작하기

Colab은 주피터 서버와 유사하지만 몇가지 알고가야할 부분이 있습니다.

 

  • 최대 12시간까지만 작업이 가능합니다.
    • Learning 상태로 방치해두면 중간에 커널이 죽은것을 보실수도 있습니다. 따라서 중간중간 weight와 loss를 저장하는 코드를 넣어야합니다.
  • 하드웨어 가속기(GPU/TPU)를 제공합니다.
    • [수정 -> 노트 설정] 또는 [런타임 -> 런타임 유형 변경] 에서 설정 
    • 암호화 화폐 채굴등을 수행할 경우 서비스 차단이 이루어 질 수 있습니다.
    • TPU는 머신러닝을 위해 Google에서 자체적으로 제작한 하드웨어로 GPU보다 월등한 성능을 보인다고합니다.
    • 실제 GPU와 TPU 차이를 테스트해본 적은 없으며, Keras 라이브러리는 TPU를 자동으로 잡지 못하기 때문에 별도 코드를 추가해줘야합니다.
    • GPU의 경우 약 14.6GB의 크기를 제공합니다.
  • 구글 드라이브와 연동이 가능합니다.
    • 파일을 직접 업로드하여 사용하는 것보다 구글 드라이브에 파일을 업로드하고 연동하는 것이 빠릅니다.
    • 코랩에 작성된 코드들은 모두 구글 드라이브에 저장됩니다.

 

2. Colab 알아보기

  • 단축키 설정하기 : [도구 -> 단축키]에서 원하는 단축키로 설정이 가능합니다.
  • 테마 : [도구 -> 환경설정]에서 "Dark"모드로 변경이 가능합니다.
  • Github 백업하기 : [파일 -> Github에 사본 저장]을 통해 Github와 연동하여 사본을 저장할 수 있습니다.
  • 입력효과 넣기 : [도구 -> 환경설정 -> 기타]에서 파워레벨을 설정에 따라 입력시 불꽃이 튀기는 효과를 줄 수 있습니다.
  • 리눅스 OS 버전 : Ubuntu 18.04를 사용중입니다.(현재 19년 7월 기준)

 

  • 하드웨어 사양 (CPU, RAM, DISK)

 

  • GPU 사양

'머신러닝 > 데이터 전처리' 카테고리의 다른 글

[Colaboratory] 구글 Colab 사용하기  (1) 2019.07.17
[데이터전처리] 1. Pandas in python  (0) 2019.05.30
  1. update 2019.10.08 22:32

    colab에서 selenium을 사용시
    chromedriver경로가 문제가 있는지 계속 에러가 납니다

    알수있을까요 부탁드립니다
    !apt-get update
    !apt install chromium-chromedriver
    !cp /usr/lib/chromium-browser/chromedriver /usr/bin
    !pip install selenium
    from selenium import webdriver
    options.add_argument('–headless')
    options.add_argument('–no-sandbox')
    options.add_argument('–disable-dev-shm-usage')
    options = webdriver.ChromeOptions()
    driver = webdriver.Chrome('chromedriver' ,options=options)
    driver.get('https://whoer.net/')

    =============================================================
    WebDriverException Traceback (most recent call last)
    <ipython-input-43-85b17a6c99df> in <module>()
    11 chromedriver = '/usr/bin/chromedriver'
    12 #driver = webdriver.Chrome("/usr/lib/chromium-browser/chromedriver")
    ---> 13 driver = webdriver.Chrome('chromedriver' ,options=options)
    14
    15

    4 frames
    /usr/local/lib/python3.6/dist-packages/selenium/webdriver/remote/errorhandler.py in check_response(self, response)
    240 alert_text = value['alert'].get('text')
    241 raise exception_class(message, screen, stacktrace, alert_text)
    --> 242 raise exception_class(message, screen, stacktrace)
    243
    244 def _value_or_default(self, obj, key, default):

    WebDriverException: Message: unknown error: Chrome failed to start: exited abnormally
    (unknown error: DevToolsActivePort file doesn't exist)
    (The process started from chrome location /usr/bin/chromium-browser is no longer running, so ChromeDriver is assuming that Chrome has crashed.)

    이런 에러가 납니다

몇가지 중요한 Widget 들에 대해서 다루겠습니다.

Widget의 이름과 해당 Widget이 갖고있는 주요 속성에 대해서 다루며, MainActivity.java에서 속성값을 변경하는 부분을 다룹니다.

 

 

1. TextView

1) XML

id : 객체를 구분하는 ID ( TV1 이라고 설정했습니다. )

Text : TextView에 들어갈 문자열

TextAppearance : 텍스트의 테마를 설정할 수 있습니다.

(기본적으로 몇개의 샘플 테마들이 저장되어있습니다.)

 

 

2) Java

다음으로 MainActivity.java파일을 아래와 같이 변경했습니다.

 

이전에 xml파일에서 만든 TV1이라는 TextView의 주소값을 갖고와서 저장할 변수가 필요합니다.

 

TextView text1 라는 코드를 통해서 text1이라는 변수를 만들었고요.

 

이후 setContentView를 통해서 activity_main.xml을 갖고온 후 findViewById라는 메서드를 통해서 위에서 만든 TextView의 ID값(TV1)을 통해서 해당 TextView를 갖고와 text1 변수에 넣어주었습니다.

 

이후 setText 메서드를 통해서 원하는 문자열도 글자를 변경할 수 있도록 해주었습니다.

(기존 문자열을 갖고오는 메서드는 getText입니다.)

 

실행결과

 

 

2. Button

1) XML

Button

다음으로 Button 위젯입니다.

 

id : btn으로 설정해주었습니다.

text : 버튼에 입력될 기본 문자열입니다.

onClick : 버튼을 누르면 실행될 액션

 

2) Java

아래는 Java파일에서 Button의 onClick메서드를 설정해주는 과정입니다.

 

보게되면 btnListener라는 class가 추가된 것을 볼 수 있습니다.

 

그리고 해당 클래스 객체를 생성해서 btn의 OnClickListener로 설정해 주는 것을 볼 수 있습니다.

 

Listener라는 녀석은 어떤 위젯이 정해져있는 특정한 액션을 실시할 때를 기다렸다가, 해당 액션이 발생되면 작성된 코드(기능)를 수행하는 기능을 하는 녀석입니다.

 

따라서 button(btn)을 누르면 Text가 변경되는 것을 볼 수 있습니다.

 

실행결과

 

의문... 그럼 Button 속성에 있던 onClick이라는 녀석은 어떻게 쓰는걸까?

onClick 속성과 같이 자주사용되는 기능에 한정해서 다른 방식으로 해당 기능을 수행할 수 있는 방법을 제공하고 있습니다.

 

먼저 아래와 같이 Java코드를 작성해줍니다.

 

Java

간단합니다. 별도 클래스 작업잆이 단 하나의 메서드를 생성하면 됩니다.

이렇게 해주고 xml파일에서 버튼의 onClick메서드를 보세요.

 

그럼 위와같이 방금 만든 녀석이 보이게 됩니다.

 

그냥 onClick에 저 녀석을 넣어주고, 실행하면 아래와 같이 잘 수행됩니다.

 

 

실행화면

간단하죠?

 

하지만, 자주사용되는 몇몇 기능에 한정되어 지원하기 때문에, 두가지 방법 모두 알아두셔야만 합니다!!

 

 

3. TextView + 2 Button

Q, 만약 버튼이 2개 이상이고, 버튼을 누르면 어떤 버튼이 눌렸는지 알려주는 TextView가 존재한다고 합니다. 그럼 하나의 Listener를 통해서 다수의 버튼 중 어떤 버튼이 눌렸는지 알려줄 수 있을까요?

 

A. 어렵지 않습니다. onClick(View v) 이라는 부분에 v라는 매개변수가 존재하는 것을 볼 수 있습니다.

이 v라는 녀석이 통해서 버튼을 구분할 수 있습니다.

 

 

위와같이 2개의 버튼과 textView를 만들었습니다. (괄호 안에 값 = ID)

 

다음으로 Java파일 내용입니다.

 

Java

보게되면, 거의 큰 차이는 없고, btnListener 영역에서의 차이가 있습니다.

 

v.getId() 라는 메서드를 통해서 버튼의 id값을 갖고오는데요. 보게되면 int값으로 저장하는 것을 볼 수 있습니다.

 

즉, 우리가 xml에서 작성한 id값을 java코드에서 갖고올때 문자열이 원형으로 갖고 오는것이 아니라, 구분할 수 있는 특정한 숫자값으로 갖고 온다는 것을 추측할 수 있습니다.

 

이렇게 갖고온 값은 R.id.btn 의 값과 동일합니다.

 

따라서 위와같은 방식으로 버튼을 구분할 수 있습니다.

 

 

 

다음으로는 라디오 버튼과 체크박스 위젯을 알아보겠습니다.

 

1. View

안드로이드 앱에서 보이는 모든 요소들을 View라고하며, 이것은 View라는 Class를 상속받아 사용됩니다.

 

전에 보았던 activity_main.xml에서 '버튼', '이미지뷰', '텍스트상자' 등을 추가하면 이것들은 하나하나가 View클래스를 상속받아 사용되게됩니다.

 

즉, View라는 클래스는 모든 UI요소들의 부모클래스가 되게됩니다.

 

View는 레이아웃위젯으로 분류됩니다.

 

2. Widget(위젯)과 Layout(레이아웃)

위젯은 버튼, 텍스트상자와 같이 특별한 기능을 갖고있는 View를 의미합니다.

 

간단하죠?

 

다음으로 레이아웃은 컨테이너라고 불리기도 합니다.

 

독립적으로 특별한 기능을 갖고있다기 보다는 다른 뷰(레이아웃/위젯)를 포함하는 틀이라고 볼 수 있습니다.

 

쉽게 생각해서 한글에서의 표가 내부에 글자나 이미지 또는 또 다른 표를 넣을 수 있듯이, 레이아웃도 내부에 Button이나 ImageView와 같은 위젯 또는 또 다른 Layout을 넣을 수 있습니다.

 

여러 종류의 레이아웃들이 존재하는데 크게 Linear와 Relative로 볼 수 있습니다.

3. Linear Layout

가장 많이 사용되는 레이아웃의 종류로 좌에서 우 또는 상에서 하로 내부에 View를 쌓는 Layout입니다.

 

처음 프로젝트를 생성하고, [ activity_main.xml ] 의 하단에보면 Design과 Text가 있는데 Text로 이동해보면 아래와 같은 모습을 볼 수 잇습니다.

 

activity_main.xml의 Text

Text영을 클릭하면 좌측에는 xml코드가, 우측에는 xml의 이미지 미리보기가 표시됩니다.

 

여기서 조금 수정해서 Linear Layout으로 변경해보겠습니다.

 

 

위와같이 처음 Layout영역을 LinearLayout으로 변경해주고, android:orientation="vertical" 속성을 추가해주었습니다.

 

일부 입력으로 자동완성이 가능해서 복사 가능하게 올리지는 않았습니다.

 

다시 Design으로 돌아가서 Button들을 몇개 넣어보겠습니다. (좌측의 Buttons에서 몇개의 버튼들을 끌어넣으면 됩니다.)

 

5개의 Button을 넣었더니 미리보기 영역에 위와같이 버튼들이 들어간 것을 볼 수 있습니다.

 

즉, LinearLayout의 vertical 속성은 상에서 하 방향으로 View들이 들어가는 것을 볼 수 있습니다.

 

만약 horizontal으로 값을 넣었다면 좌에서 우로 View들이 들어가는 것을 보실 수 있습니다.

 

또한 Button과 같은 View들은 여러개의 속성들을 갖고있습니다.

 

Design영역에서 Button을 클릭하면 우측에 속성들이 표시되는 것을 볼 수 있습니다.

 

몇가지 대표적인 것들을 정리하면 아래와 같습니다.

 

  • id : xml에서 생성한 View를 구분하는 명칭입니다.
  • layout_width : View의 가로 길이
  • layout_height : View의 세로 길이
  • margin : View의 외부 여백
  • padding : view의 내부 여백
  • layout_gravity : View의 위치 정렬 기준
  • gravity : View 내부 요소들의 정렬 기준
  • background : View 배경(색/이미지 등)

4. Relative Layout

Relative Layout은 레이아웃 내부의 다른 View들 간의 관계를 통해서 Layout내부에서의 위치를 결정하는 종류의 Layout입니다.

 

예를들어 Button1과 Button2가 있다면, [ Button2는 Button1의 5dp아래에 존재한다 ] 라고 정의하는 형식입니다.

 

간단한...가요?

 

실제로 만들어서 건들여보시면 쉽게 이해하실 수 있습니다.

간단하게 Activity의 상태변화에 따라 실행되는 메서드들에 대해서 다루고 넘어갑니다.

(Activity의 생명주기 변화에 따른 실행 메서드를 의미합니다.)

 

- on 메서드

  • onCreate : Activity 생성될 때, 화면회전이 발생할 때 자동으로 호출됨
  • onStart : onCreate 실행 후, Activity가 정지상태에서 활동상태로 이동할 때 호출(홈버튼눌러서 화면 이동 후 다시 앱으로 돌아올 때)
  • onResume : onStart 실행 후, Activity가 일시정지 후 다시 돌아올 때 호출(일시정지 = 앱 위에 팝업창이 떴다가 없어질 때)
  • onRestart : Activity가 정지 상태 후 활동 상태로 돌아갈 때, onStart 이전에 실행됨
  • onPause : 일시 정지 상태일 때 호출, 화면상에서 Activity가 사라지거나, 팝업창 등이 나타날 때 호출
  • onStop : Activity가 화면에서 사라질 경우
  • onDestroy : 현재 Activity(APP)가 완전히 제거될 경우(앱종료)

 

onCreate : 앱이 최초로 실행할 때 수행되야 하는 코드를 넣어줍니다.

onPause : 앱이 무슨 이유로든 사용불가 상태가 될 경우 수행될 코드를 넣어줍니다.

onResume : 앱이 수행상태로 이동했을 때 필요한 코드를 넣어줍니다.

onDestroy : 앱이 종료될 경우 필요한 코드를 넣어줍니다.

+ Recent posts