728x90
반응형

1. 주소

https://www.netmanias.com/ko/post/blog/6264/nat-network-protocol-p2p/p2p-nat-nat-traversal-technic-rfc-5128-part-1-relaying-connection-reversal

- 네트워크 관련 기술들 내용 정리 좋음

 

P2P와 NAT: NAT 통과 기법 소개 (RFC 5128) - 1편: Relaying & Connection Reversal

오늘은 사설 IP 주소를 가지는 두 단말 간에 P2P 통신이 가능하도록 하는 기술(NAT Traversal이라 부름)에 대해 소개 해 드리겠습니다. RFC 5128(State of P2P Communication across NATs - Informational)에서 설명하고

www.netmanias.com

 

 

 

728x90
반응형
728x90
반응형

1. 목적 

- [프로젝트> 그룹> 커뮤니케이션] 중 화상 회의/영상 채팅 기술을 구현하기 위한 연습코드

- TCP/IP 연결이 성립된 상태에서 1:1로 실시간 단방향 영상 전송을 구현

 

2. 구성

- 노트북 카메라 연결 -> 영상 캡쳐 후 파일 저장 -> 저장된 이미지 파일을 TCP/IP 소켓으로 전송해줌 -> 클라이언트에서는 파일로 받은 후 이미지를 보여줌

- 언어는 C/C++, 네트워크는 윈도우 소켓, 형식은 윈도우 실행파일(exe), 라이브러리는 동적로딩으로 활용(DLL 파일 따로 필요)

- 베이스 코드 : https://hwan001.tistory.com/54?category=747955

 

3. 코드

// windows socket
#include <winsock2.h>

// windows
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// opencv 
#include <opencv2/highgui.hpp>
#include <opencv2/opencv.hpp>

using namespace cv;

#pragma comment(lib, "ws2_32.lib")

// Socket
#define IP "127.0.0.1"
#define PORT 6667
#define BUFSIZE 44000

void server();
void client(char *server_ip);
void client_send(SOCKET *sock);
void server_recv(SOCKET *client_sock);

int main() {
    int sel;
    char server_ip[21];
    printf("1: server\n2:client\n3.tmp file clear >");
    scanf_s("%d", &sel);
    switch (sel)
    {
    case 1: // 서버로 수신
        server();
        break;
    case 2: // 클라이언트로 전송
        printf("Server IP : ");
        scanf_s("%s", server_ip, 21);
        if (!strcmp(server_ip, "test")) {
            strcpy(server_ip, IP);
        }
        printf("%s\n", server_ip);
        client(server_ip);
        break;
    case 3: // 임시 파일 삭제
        remove("recv.jpg");
        remove("tmp.jpg");
        break;
    default:
        break;
    }
    return 0;
}

void client(char *server_ip) {
    // WSA  초기화
    WSADATA wsaData;
    WSAStartup(MAKEWORD(2, 2), &wsaData);
    // 소켓 만들기
    SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
    SOCKADDR_IN addr;
    // 소켓 설정
    ZeroMemory(&addr, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = inet_addr(server_ip);
    addr.sin_port = htons(PORT);
    
    // TCP 연결 시도
    connect(sock, (SOCKADDR *)&addr, sizeof(addr));
    // 영상 전송
    client_send(&sock);
    // 마무리
    closesocket(sock);
    WSACleanup();
    remove("tmp.jpg");
}

void server() {
    WSADATA wsaData;
    WSAStartup(MAKEWORD(2, 2), &wsaData);
    // 소켓 만들기
    SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
    SOCKADDR_IN addr;
    // 소켓 설정
    ZeroMemory(&addr, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = INADDR_ANY;
    addr.sin_port = htons(PORT);
    
    bind(sock, (SOCKADDR *)&addr, sizeof(addr));
    listen(sock, 2);
    printf("listen ok\n");
    // 클라이언트 연결 요청 수락
    SOCKADDR_IN client_addr;
    ZeroMemory(&client_addr, sizeof(client_addr));
    int nlen = sizeof(client_addr);
    SOCKET client_sock = accept(sock, (SOCKADDR *)&client_addr, &nlen);
    // TCP 연결 수립
    printf("clinet IP : %s\n", inet_ntoa(client_addr.sin_addr));
    // 영상 수신
    server_recv(&client_sock);
    // 마무리
    closesocket(sock);
    WSACleanup();
    remove("recv.jpg");
}

// server function
void server_recv(SOCKET *client_sock) {
    FILE *fp = NULL;
    char buf[BUFSIZE];
    char buf2[BUFSIZE];
    Mat image;
    while (1) {
        // 이미지 파일 수신
        ZeroMemory(buf, NULL);
        fopen_s(&fp, "recv.jpg", "wb");
        // 버퍼 채우기
        recv(*client_sock, buf, sizeof(buf), 0);
        fwrite(buf, BUFSIZE, 1, fp);
        // 버퍼를 두번 받으면 딜레이가 사라진다??
        recv(*client_sock, buf2, sizeof(buf2), 0);
        fwrite(buf2, BUFSIZE, 1, fp);
        fclose(fp);
        // 이미지 보여주기
        image = imread("recv.jpg");
        if (image.empty()) { continue; }
        else imshow("recv", image);
        // esc 누르면 종료
        if (waitKey(33) > 0) break;
    }
}

// client fuction
void client_send(SOCKET *sock) {
    FILE *fp = NULL;
    Mat image;
    VideoCapture cap(0);
    char buf[BUFSIZE];
    while (1) {
        // 카메라 접근 후 파일로 작성
        cap.read(image);
        resize(image, image, Size(300, 400));
        imwrite("tmp.jpg", image);
        // 파일 열어서 읽고 전송
        ZeroMemory(buf, NULL);
        fopen_s(&fp, "tmp.jpg", "rb");
        fread(buf, BUFSIZE, 1, fp);
        send(*sock, buf, sizeof(buf), 0);
        fclose(fp);
    }
}
 

4. 결과

 

 

5. 추가 기능

- 양방향 영상 송수신, IOCP, P2P, 코덱

728x90
반응형
728x90
반응형

 

** UiPath 연습용 프로젝트, 현재 포스팅 정리 중

목표 : 매일 정해진 시간에 구독자에게 네이버 오늘의 회화를 보내주는 로봇 제작

 

 

1. 네이버 오늘의 회화 사이트

https://learn.dict.naver.com/conversation#/endic/

 

 

2. 프로세스 만들기

 

3. 플로우 차트 구성 

 

 

 

 

4. 느낀점 

- 작동은 되지만 딜레이는 어시스턴트나 오케스트레이터의 스케줄 기능을 활용하는 게 더 나음

 

 

 

 

 

 

728x90
반응형
728x90
반응형


** 개인 공부용, 내용 중 잘못된 부분이나 시간이 지나면서 변경된 부분이 있을 수 있음


1. 시작 (환경 설정)


Step 1. UiPath Studio Download -> https://www.uipath.com/ko/ 


Step 2. 커뮤니티 클라우드 에디션 선택 (무료)


Step 3. Sign up (아무거나 편한걸로 로그인 하면 됨.)


Step 4. 입력하다보면 나오는 화면. (블로그 글 작성 전에 만들어서 로그인시 앞에 내용이 생략됨, 대충 적어달라는 내용 적어주면 됨)



Step 5.  UiPath Studio 설치 

  


Step 6. UiPath Studio UI

** 오케스트레이터, 커뮤니티, 아카데미 둥 많은 유혹이 있지만 일단 스튜디오 설치부터 하기








2. UiPath Academy


Step 1. 자체적으로 운영하는 교육용 사이트로 검색으로 통해서 들어가도 좋고, 스튜디오 실행시 뜨는 팝업 창에서 들어가도 됨. (동영상 시청, 자습서, 아카데미 중 아카데미 클릭)


Step 2. 1번 (Learning Plan)클릭 후 2번, 3번 순으로 학습 (RPA Developer Foundation -> RPA Developer Advanced)


Step 3. Foundation 내부 자료들.


** 기초 문법 공부 하려면 하나씩 봐주면 됨.

728x90
반응형
728x90
반응형

 (size : 300) / (size : 640)


** 마지막 수정일 : 2020-12-19

** 찾아가면서 공부하는 중이라 정확하지 않은 정보가 있을 수 있음. (#F15F5F)

** 주석 (#22741C)


1. 용어 해설 (size : 12/ 10)

- RPA : Robotic Process Automation  https://namu.wiki/w/RPA

- UIPath Studio : UiPath 사의 RPA 툴  https://www.uipath.com/ko/

- UiPath Studio X : 컴퓨터 비전공자 버전

- Attended Robot : 유인로봇, 사람과 소통하면서 작업 시행 

- Unattended Robot : 무인로봇, 사람과 소통하지 않아도 알아서 정해진 작업 시행 

- Orchestrator : 로봇 관리, 모니터링, 원격 실행, 패키지/라이브러리 배포 등의 역할을 하는 서버



2. 해볼거

- 유인 로봇(Attended) : 웹에서 데이터 가져와서 파일로 저장, 파일 읽어서 데이터 정리

- 무인 로봇(Unattended) : 

- 오케스트레이터 : 서버 구축, 대량 데이터 처리(Queue 활용 병렬 처리), 패키지 배포, 라이브러리 배포, 프로세스 원격 실행 및 스케줄링

- 기타 : 카카오톡 자동응답, 리스트에 있는 사람들에게 메일 보내주기, 주식관련 정보 수집, 자동 수강신청(예매 등), OCR 기능



3. 느낀점 

- 윈도우에서만 작동하는게 아쉬움 

- 활용도는 개발자 역량에 따라 다름

- 회사 업무가 반복적이고 비효율적이라면  업무 효율을 올릴 수 있을 듯

- 툴에 코드가 거의 없음. (컴퓨터 비전공자도 쉽게 접근 가능 -> VB/ C# 코드 활용하긴 함)

728x90
반응형
728x90
반응형

 

코드 1 - i(2 ~ N)를 j(2 ~ i)로 나누기

 N을 입력받고 i를 2~N까지 1씩 더한다.

j가 2부터 i에 도달할때까지 1씩 더하면서 i와 나누어 떨어지면 (1과 자기 자신을 제외한 인수가 있으므로) 소수가 아님.

위 연산을 반복해서 0~N 까지 소수의 개수를 하나하나 판단하여 카운팅한다.

 

각 범위를 계산하며 시간을 측정해본 결과는 아래 표와 같다.

 

#include<stdio.h>
#include<math.h>

int main() {
    int i, j, cnt=0, flag=1;
    unsigned int min, max;

	// 범위 입력
    printf("min : ");
    scanf_s("%d", &min);
    printf("max : ");
    scanf_s("%d", &max);

	// 2보다 작은 최소 범위가 입력되면 2로 고정
    if (min < 2) min = 2;
	
    printf("입력 받은 범위 내의 소수");
    // i가 입력받은 최소 범위부터 최대 범위까지 반복
    for (i = min; i < max; i++) 
    {
        flag = 1; // 현재수가 소수라고 가정하고 시작
        
    	// j는 2부터 현재의 i 전까지 증가
        for (j = 2; j < i; j++) 
        {
        	// i와 j를 나눈 나머지가 존재하면 소수가 아님
            if (i % j == 0) 
            {
                flag = 0; // flag가 0이면 현재 수(i)는 소수가 아님
                break; // 더 이상 j로 나누어 줄 필요가 없으므로 탈출
            }
        }
		
        // 위에서 판단된 결과가 소수이면(0이 아니면)
        if (flag) 
        {
            cnt++; // 개수를 증가시킴 (입력 받은 범위 내의 소수 개수)
            printf("%d\t", i); // 출력
            
            if (cnt % 5 == 0) 
            {
            	printf("\n"); // 5개 단위로 끊음
            }
        }
    }

    printf("\n%d ~ %d 사이의 소수 개수 : %d개\n", min, max, cnt);

    return 0;
}

 

범위 개수 시간(s)
2~100 25 0.000s
2~1000 168 0.001s
2~10000 1229 0.028s
2~100000 9592 0.973s
2~1000000 78498 119.606s
2~10000000 - -

 


 

코드 2 - i (2 ~ N)를 j (2 ~ i / j)로 나누기

 현재 수 i가 2의 배수일 경우 i/2 * 2 = i, 3의 배수일 경우 i/3 * 3 = i, 5와 7의 배수일 경우는 i/5 * 5 = i, i/7 * 7 = i 가 성립한다. (4, 6등은 2와 3의 배수이므로 해당 범위에 포함된다.)
위 공식을 일반화시키면 아래와 같고,
i/n * n = i
여기서 i의 소인수는 j와 i/j의 곱셈이므로 j는 i/j보다 클 수 없다는 가설을 적용하여 코드를 작성했다.
(수가 커질수록 더 많은 범위의 계산이 생략되므로 속도가 빨라짐)

아래 표를 보면 코드1의 방식보다 좀 더 개선된 걸 볼 수 있다.
 
#include<stdio.h>
#include<math.h>
#include<time.h>

void test(int min, int max) 
{
    clock_t start, end;
    float res;
    int i, j, cnt = 0, flag;

    start = clock();
    for (i = min; i < max; i++)
    {
        flag = 1;
		
        // 기존과 달라진 부분, j로 확인 하는 범위를 i와 현재 j의 나눈 몫까지로 줄였음
        for (j = 2; j <= (int)(i / j); j++)
        {
            if (i%j == 0)
            {
                flag = 0;
                break;
            }
        }

        if (flag)
        {
            cnt++;
        }
    }
    end = clock();

    res = (float)(end - start) / CLOCKS_PER_SEC;

    printf("%d~%d : %d개\t%.3fms\n", min, max, cnt, res);
}

int main() {
    int arr[] = {100, 1000, 10000, 100000, 1000000, 10000000, 1000000000};

    for (int i = 0; i < (int)(sizeof(arr) / sizeof(int)); i++)
    {
        test(2, arr[i]);
    }
    return 0;
}

 

범위 개수 시간(s)
2~100 25 0.000s
2~1000 168 0.000s
2~10000 1229 0.001s
2~100000 9592 0.028s
2~1000000 78498 0.359s
2~10000000 664579 7.392s
2~100000000 5761455 202.174s
2~1000000000 50847534 5087.694s
2~10000000000 - -

 


 

코드 3 - 에라토스테네스의 체

 에라토스테네스의 체를 활용하여 미리 계산된 소수 여부 테이블을 참조하는 방식으로 개수 확인한다.

작은 범위에서는 위의 알고리즘 들과 비슷하거나 느리지만 큰 수의 범위로 가면 훨씬 빠른걸 볼 수 있다.

 

#include <iostream>

using namespace std;

typedef unsigned long long ll;

/*
* input : int m
* output : 1부터 m까지의 소수 여부를 sizeof(bool) * (m+1)크기의 bool * 형태로 반환한다.
* 사용 시 반환된 bool array에 해당 자연수를 조회하면 소수 여부를 알 수 있다.
*/
bool *Sieve_of_Eratosthenes(ll m) {
    bool* arr = new bool[m + 1];

    memset(arr, 1, sizeof(bool) * (m+1));
    arr[0] = false;
    arr[0] = false;

    for (ll i = 2; i < m + 1; i++) {
        if (arr[i] == true) {
            for (ll j = i * 2; j < m + 1; j += i) {
                arr[j] = false;
            }
        }
    }

    return arr;
}

int main() {
    clock_t start, end;
    ll N, M;
    ll sum=0;

    start = clock();
    cin >> N >> M;
    bool* arr = Sieve_of_Eratosthenes(M);

    for (ll i = N; i <= M; i++) {
        if (arr[i]) {
            sum++;
        }
    }

    end = clock();
    float res = (float)(end - start) / CLOCKS_PER_SEC;
    cout << "" << N << " " << M << " " << sum << ", " << res << "ms" << endl;
    
    return 0;
}
범위 개수 시간(s)
2~100 25 7.149
2~1000 168 9.231
2~10000 1229 14.213
... - -
2~100000000 5761455 53.387
2~1000000000 50847534 23.744
2~10000000000 455052511 252.08
2~100000000000 -

 


 

참고

  • 계산 범위의 조절로 100만에서 1억으로 향상되었지만 여전히 큰 수를 처리하기엔 어려움
  • 에라토스테네스의 체를 활용할 경우 테이블 생성으로 인해 작은 수 범위에서는 더 오래걸리지만,
    큰 수에서는 훨씬 적은 시간이 걸림. (1억에서 100억 단위로 향상됨)
  • Openssl을 활용한 더 큰 소수의 활용은 아래 블로그에 있다.

https://nitwit.tistory.com/17

 

암호학 - 소수 판별

프로그래밍 입문 단계에서 흔히들 과제로 많이 접해보는 문제이다. 특정 수를 입력했을때 이녀석이 소수인지 아닌지 판별하는 알고리즘을 짜보라는 식의 과제. 만약 여러분이라면 어떻게 풀겠

nitwit.tistory.com

 

 

728x90
반응형
728x90
반응형

** 티스토리 에디터 변경으로 아래 기능은 현재 사용 제한

 

1. 주소

https://colorscripter.com/

 

2. 사용

 

3. 블로그 적용

- HTML 또는 클립보드에 복사 클릭

- HTML 시 외부 컨텐츠 > HTML에 복사 붙혀넣기

- 클립보스 시 ctrl+v 

 

728x90
반응형
728x90
반응형

 

 

빠른 모듈로 거듭제곱법 (개념 이해하기) | 암호학이란? | Khan Academy

 

ko.khanacademy.org

 



2. 코드

#include "stdafx.h"
#include <ctype.h>
#include <math.h>

int gcd(int a, int b);
int RSA(int n, int m, int d); 

int main(){
    // 키 생성
    //int p = 13, q = 37;
    //int p = 11, q = 13;
    int p = 17, q = 13;

    int n, e, d, f;

    n = p * q;
    f = (p-1) * (q-1);

    // e 결정
    for (int i = 2; i < f; i++) {
        // 서로소 판단
        if (gcd(p - 1, i) == 1 && gcd(q - 1, i) == 1) {
            e = i;
            break;
        } 
    }

    //d 결정
    for (int i = 1; i < n; i++) {
        if ((1 + f * i) % e == 0) {
            d = (1 + f * i) / e; 
            break;
        }
    }

    // 소수에 따라 자동 계산된 변수 값
    printf("p\tq\tn\te\td\tf\n");
    printf("%d\t%d\t%d\t%d\t%d\t%d\n\n", p, q, n, e, d, f);

    // 암호화
    int msg = 'b';
    printf("msg : %c\n", msg);

    int c = RSA(n, msg, e);
    printf("c : %c\n", c);

    // 복호화
    int msg2 = RSA(n, c, d);
    printf("msg : %c\n", msg2);

    return 0;
}

// 암복호화를 위한 모듈로 연산을 수행 (n, d는 공개키/ 개인키, m은 메시지)
int RSA(int n, int m, int d) {
    int bin1[10] = { 0, };
    int tmp, j = 1;
    unsigned long long x_tmp = 1; 
    int x[10]; // m^2^0~9 mod n

    // 거듭 제곱법 구현을 위한 값 미리 저장
    x[0] = (unsigned long long)pow(m, 1) % n;
    for (int i = 1; i < 10; i++) {
        x[i] = (x[i - 1] * x[i - 1]) % n;
    }

    // 지수를 이진수로 변환 (구현 편의성을 위해 그냥 역으로 넣음) 
    for (int i = 0; d > 0; i++) {
        tmp = d % 2;
        d /= 2;
        bin1[i] = tmp;
    }

    // 이진수가 1일 떄만 미리 계산된 값 곱셈
    for (int i = 0; i < 10; i++) {
        if (bin1[i] == 1) {
            x_tmp *= x[i];
        }
    }

    return x_tmp % n; // 곱셈 합을 모듈로해서 반환
}

// 최대 공약수
int gcd(int a, int b) {
    int tmp, n;

    if (a<b) {
        tmp = a;
        a = b;
        b = tmp;
    }

    while (b != 0) {
        n = a % b;
        a = b;
        b = n;
    }

    return a;
}

3. 결과


4. 참고 사항

 - 메르센 소수 같은 빅넘버를 처리하기엔 부적합함 (이 경우  OpenSSL 활용)

 - 거듭 제곱법 구현 함수 내 배열을 10으로 고정해두었으나 배열 크기 조정으로 어느정도 큰 소수

   (x_tmp 최대값, unsigned long long) 까지는 연산이 가능함.

- 문자를 하나씩 암호화 하면 같은 문자는 같은 값으로? 암호화됨. (블록 단위 암호화 필요)

  ex) testtest -> abcaabca 

- 자료형 크기 고려했을 때 문자를 대충 4바이트 단위까지 합쳐서 연산가능할 듯

  ex) asdf  -> 16진수변환 한번에 연산 등등

 

 

 


내용 수정

2024-01-21(일)

- 기존 코드에서 잘못된 부분을 확인하여 수정이 필요한 부분을 적어두었음

- e를 결정하는 부분에서 e와 f가 서로소인 부분이 확인 되어야 하기 때문에 기존 코드의 gcd(p - 1, i) == 1 && gcd(q - 1, i) == 1 부분이 제거 되고 아래처럼 수정되어야 함

f = (p-1) * (q-1);

// e 결정
for (int i = 2; i < f; i++) {
    if (gcd(i, f) == 1) {
        e = i;
        break;
    }
}

 

728x90
반응형
728x90
반응형

1. Visual Studio 2022 Community 설치

.NET 데스크톱 개발 선택 후 설치

 

2. 새 프로젝트 만들기 > WPF 앱 (.NET Framework) 선택

프로젝트 생성


프로젝트 생성 2

 

3. XAML/ 디자인 편집기와 C# 편집기

xaml/디자인 편집기


C# 편집기

 

4. 빌드 및 실행

빌드 및 실행 성공

728x90
반응형
728x90
반응형
728x90
반응형
728x90
반응형
728x90
반응형
728x90
반응형
728x90
반응형
728x90
반응형
728x90
반응형
728x90
반응형
728x90
반응형
728x90
반응형

1. GitHub > Sign Up

 

 

728x90
반응형
728x90
반응형

<script type="text/javascript">
if ( window.location.pathname == '/' ) {
     location.href = 'URL';
}
</script>

728x90
반응형

'기타 > 블로그' 카테고리의 다른 글

[tip] 블로그에 코드 올릴떄 쓰는거  (0) 2020.05.17
[tip] Tistory 단축키 만들기  (0) 2016.12.12
728x90
반응형

개인적으로 공부한 내용 정리한 블로그입니다.

잘못된 부분 발견 시 댓글로 알려주시면 감사하겠습니다.

728x90
반응형
728x90
반응형

1. 스크립트

 

2. 결과

 

 

728x90
반응형
728x90
반응형

https://protonmail.com/

 

728x90
반응형
728x90
반응형

http://shephexd.github.io/2018/06/21/Tensorflow_install.html


https://stackoverflow.com/questions/6622454/cuda-incompatible-with-my-gcc-version


http://noota.tistory.com/entry/우분투에서-gcc-손쉽게-설치하기



# 작성 중 - 20181215

728x90
반응형

+ Recent posts