Post

젠킨스 다운로드 주소

http://jenkins-ci.org/

 

윈도우 버전을 다운로드 받은 후 설치한다

(별다른 설정은 없다)

다 설치하면 http://localhost:8080/ 로 접속한다.

 

그런데 젠킨스 메인화면이 아니라 Unlock Jenkins 라고 뜬다

 

Unlock Jenkins

To ensure Jenkins is securely set up by the administrator, a password has been written to the log (not sure where to find it?) and this file on the server:

C:\Program Files (x86)\Jenkins\secrets\initialAdminPassword

Please copy the password from either location and paste it below.

 

위에 적혀져 있는대로

C:\Program Files (x86)\Jenkins\secrets 폴더에서 \initialAdminPassword 파일에 적힌 비밀번호를

Administrator password 칸에 입력하면 된다,

그 후 플러그인 설치 선택 창이 나온다.

나는 svn 쓸거라서 suggeste 를 선택했다.

(일단 기본으로 해보고 안되면 다시 설치)

 

 

그 다음 계정 정보 입력창( Create First Admin User )이 나온다.

알맞게 다 입력하면 Jenkins 메인화면이 나온다.

 

 

 

 

Post

VirtualBox 복사 붙여넣기

맨처음 VirtualBox를 깔면 호스트 <-> 게스트 간의 복사,붙여넣기가 되지 않는다.

 

 

 

 

 

 

해당 게스트 설정을 위와 같이 하면 복사, 붙여넣기가 잘 된다.

 

 

그런데 그전에 게스트 확장 CD 이미지 삽입을 해야한다.

일단 게스트 메뉴에서 장치 - 게스트 확장 CD 이미지 삽입을 누른다.

( 간혹 해상도 조절 모드가 되어서 상단 메뉴가 안보일 때가 있다.

그럴 땐 ctrl+alt+c 를 누르면 해상도 조절 모드에서 빠져나온다)

 



그리고 내 PC를 누르면 CD 드라이브(D)가 있다.

D드라이브 선택 후 vBoxWindwosAdditions 를 더블클릭해서 설치한다

(별다른 특별한 설정읎 없다. 그냥 next를 누르면된다)

 

설치 후 다시 시작된다.

그리고 양방향 복사 붙여넣기를 하면 아주 잘 된다.

 

 

Post

    public uint dwIndex

    {

        get

        {

            // 나중에 데이터 변환해야함..

            return dwIndex;

        }


        set

        {

            dwIndex = value;

        }

    }


dwIndex라는 필드에 값을 넣으니 스택오버플로우 에러가 났다.


StackOverflowException: The requested operation caused a stack overflow.

MsgText.set_dwIndex (UInt32 value) (at Assets/1_Scripte/Data/MsgText.cs:17)

MsgText.set_dwIndex (UInt32 value) (at Assets/1_Scripte/Data/MsgText.cs:17)

MsgText.set_dwIndex (UInt32 value) (at Assets/1_Scripte/Data/MsgText.cs:17)

MsgText.set_dwIndex (UInt32 value) (at Assets/1_Scripte/Data/MsgText.cs:17)

...


확인해보니 dwIndex는 선언된 변수가 아니라 자기가 가지고 있는 속성? 이고

그 속성에 값을 넣어주므로 계속 set이 호출된다는 것이다.

dwIndex = value;

=> 어? dwIndex 속성에 값을 넣어주네? set 프로퍼티 호출!

dwIndex = value;

=> 어? dwIndex 속성에 값을 넣어주네? set 프로퍼티 호출!

무한반복..

그래서 아래와 같이
필드를 선언하고, 그에 따른 프로퍼티 속성을 선언했다.
그리고 값을 넣어줄 때 속성을 넣어주니 더이상 스택 오버 플로우가 일어나지 않았다!

private uint dwIndex

public uint INDEX

{

get

      {

          // 나중에 데이터 변환해야함..

          return dwIndex;

      }


      set

      {

          dwIndex = value;

      }

}



'이전게시판 > C#' 카테고리의 다른 글

StreamReader 한글깨짐 오류  (0) 2018.08.10
배열보다 리스트가 좋은 이유  (0) 2017.04.30
C# var, 무명메서드, 람다식, LINQ 예제  (0) 2016.02.18

Post


StreamReader 한글깨짐 오류


유니티에서 csv 데이터를 읽는데 유독 한글만 깨졌다.

해결방법은 다음과 같다.


1. using System.Text; 포함

2. StreamReader reader = new StreamReader(Path, Encoding.Default);

StreamReader 생성 시 Encoding.Default 인자를 2번째로 인자로 넣어주기


Post

버츄얼박스 메뉴 

파일 - 환경설정 -입력

호스트 키 조합을 Ctrl + Alt

하고 나서 호스트 키 + C 하면 스케일 모드로 전환된다고 뜬다.

전환 누르면 virtualBox 화면 크기를 마음대로 조정할 수 있다

Post

구글 프로토콜 버퍼 C++ Window 예제 (Google Protocol buffer)
 
구글 프로토콜 버퍼 프로젝트 다운로드 url : https://github.com/google/protobuf/releases/tag/v2.6.1
c++ 튜토리얼 url : https://developers.google.com/protocol-buffers/docs/cpptutorial
 
이 글은 아래 구글 프로토콜 버퍼 유튜브 강의를 정리한 내용입니다. 
 
구글 프로토콜 버퍼 : 구글에서 만든 데이터 직렬화 라이브러리.
 
1. Window용 구글 프로토콜 버퍼 프로젝트 다운로드
아래 사이트에서 Protocol Buffers v2.6.1 Source code(zip) 다운로드 후 압축풀기
 
 
2. protoc.exe 파일 만들기
protobuf-2.6.1\vsprojects\protobuf.sln 을 실행한다.
(이 때 gtest, gtest_main은 컨버터 실패로 사용할 수 없음 떠도 안쓰니까 괜찮다)
libprotobuf, libprotoc 프로젝트 속성 - C/C++ - 전처리기 정의
_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS 를 추가한다
libprotobuf, libprotoc, protoc 프로젝트를 빌드한다.(빌드성공)
 
빌드 후 프로젝트 Debug 폴더에 들어가면 protoc.exe 실행파일이 생성되어있다.
이제 폴더를 새로 만들고 새폴더 안에 넣는다.
(D드라이브에 만들었고 폴더 이름은 protobufapply이다.
위치는 D:\protobufapply)
 
3. proto 파일 만들고 h, cc 파일 생성
텍스트 파일을 생성한다. 이름은 addressbook.proto
그리고 proto 파일에 아래와 같이 입력한다.
syntax = "proto2";
 
package tutorial;
 
message Person {
  required string name = 1;
  required int32 id = 2;
  optional string email = 3;
 
  enum PhoneType {
    MOBILE = 0;
    HOME = 1;
    WORK = 2;
  }
 
  message PhoneNumber {
    required string number = 1;
    optional PhoneType type = 2 [default = HOME];
  }
 
  repeated PhoneNumber phones = 4;
}
 
message AddressBook {
  repeated Person people = 1;
}
 
 
그리고 cmd 창을 열고 다음 명령어 실행한다.
그러면 addressbook.pb.h, addressbook.pb.cc 파일이 생성되어있다.
protoc -I=. --cpp_out=. addressbook.proto
( 다음과 같이 사용하라고 적혀있다 protoc -I=$SRC_DIR --cpp_out=$DST_DIR $SRC_DIR/addressbook.proto )
 
4. 직렬화 샘플 프로젝트 생성
protobufapply 폴더안에 ProjectProto 폴더 생성한다.
그리고 ProjectProto 안에 새 vs 프로젝트를 생성한다.
(콘솔응용프로그램이고 EmptyProject, Precompiled header, Security Development 전부 체크 해제)
vs 프로젝트 폴더안에 addressbook.pb.cc , addressbook.pb.h 파일을 넣어준다.
프로젝트 소스파일에서도 넣어준다.
 
protobuf-2.6.1\vsprojects\protobuf.sln 솔루션 폴더에서 Debug 폴더 안에 있는 libprotobuf.lib 라이브러리를 복사해서
프로젝트 솔루션창에 붙여넣는다.
( 내 솔루션 폴더 위치 : D:\protobuf-2.6.1\protobuf-2.6.1\vsprojects\Debug )
 
그리고 
D:\protobuf-2.6.1\protobuf-2.6.1\src 위치를 복사 한 다음 
프로젝트 속성 - 구성속성 - VC++ 디렉터리 - 포함디렉터리에 
src 위치를 붙여넣는다.
그리고 빌드.
 
성공이라면 아무것도 없는 Main 함수 대신 
듀토리얼 페이지에 있는 샘플코드 Writing A Message 를 붙여넣는다.
빌드 성공이라면
프로젝트 속성 - 구성속성 - 디버깅 - 명령인수에 D:\protobufapply\myPhonebook.bin 입력.
 

프로젝트 실행 후 알맞은 데이터를 입력한다.

그리고 모든 입력을 마쳤다면 leave blank to finish 메시지가 보일 때 엔터를 눌러 빠져나온다.
그리고 D:\protobufapply 폴더로 가면 myPhonebook.bin 파일이 생성되어있다.
 
 
 
 

Post

구글 프로토콜 버퍼를 Window에서 사용하려고 이것저것 검색하다보니

윈도우에서 리눅스 프로그램을 사용할 수 있는 Cygwin 을 알게되었다.

설치는 어렵지 않았지만 몇가지 삽질했던 것을 적어본다.


1. select Packages 선택 시 Default 만 깔지 말자

 Default 선택 설치했는데 bin 폴더에 bash가 없었다..

 그래서 그냥 ALL 설치를 했는데 그래도 없는 패키지가 있었다..

 

2. Choose a Download Site에서 사이트 선택 

http://mirror.kakao.com 

(다음에서 카카오로 바뀌었다..)


3. 

1번과 연속적인 상황인데 정말 중요한 wget이 없었다.

난 분명 all 설치해서 다 선택하고 설치된줄 알았다..

알고보니 아래 그림처럼 wget 검색 시 Web의 1.19.1-2 의 Bin? 을 한번 선택해줘야

네모박스 안이 x표시가 되고 선택이 되는거였다ㅠㅠ....


4. Cygwin Path 설정

제어판 - 시스템 - 시스템 속성 - 고급 - 환경변수 - 시스템 변수 - Path

D:\cygwin64\bin;

라고 입력

cygwin64 은 설치폴더이므로 환경마다 이름이 다를 수 있다





'이전게시판 > C, C++' 카테고리의 다른 글

Visual studio 단축키  (0) 2024.10.03
C++ csv 파일 읽기  (0) 2024.09.25
c++ 전처리기 region 이란  (0) 2018.09.30
pragma message 출력창에 내용 출력  (0) 2018.08.29
서버 파싱 중 이진수 데이터 조합  (0) 2018.06.20
flyweight(플라이웨이트) 패턴  (0) 2018.06.16
VisualStudio 줄번호 바로가기 단축키  (0) 2018.06.05
const와 포인터  (0) 2018.05.30

Post

아래의 기본 서버 예제는 문제점이 있다.

클라이언트가 많아지면 접속을 제 때 받지 못한다.

또 처리하는 부분(send)도 시간이 많이 걸리면 클라이언트 접속 대기 시간이 생긴다.

둘 다 분리되어있지 않고, 원스레드에서 해결하기 때문이다.

아래는 원스레드 서버의 처리시간이 길어지면 어떤문제점이 있는지 보여주는 예제이다.


상황설정

서버는 원스레드로, 클라이언트 접속 후에 1초걸리는 일을 처리하고 패킷을 전달한다.

클라이언트는 배치 파일을 만들어서 7개가 동시에 Connect를 요청하고 서버의 응답을 기다린다.


bat 파일은 아래와 같이 작성했다.

( ConsoleApplication2.exe 가 클라이언트다.. .;; )

 start /d "C:\Users\MyDirectory\Documents\Visual Studio 2017\ConsoleApplication2\Debug\" ConsoleApplication2.exe

 start /d "C:\Users\MyDirectory\Documents\Visual Studio 2017\ConsoleApplication2\Debug\" ConsoleApplication2.exe

 start /d "C:\Users\MyDirectory\Documents\Visual Studio 2017\ConsoleApplication2\Debug\" ConsoleApplication2.exe

 start /d "C:\Users\MyDirectory\Documents\Visual Studio 2017\ConsoleApplication2\Debug\" ConsoleApplication2.exe

 start /d "C:\Users\MyDirectory\Documents\Visual Studio 2017\ConsoleApplication2\Debug\" ConsoleApplication2.exe

 start /d "C:\Users\MyDirectory\Documents\Visual Studio 2017\ConsoleApplication2\Debug\" ConsoleApplication2.exe

 start /d "C:\Users\MyDirectory\Documents\Visual Studio 2017\ConsoleApplication2\Debug\" ConsoleApplication2.exe

<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
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
 
#define BUF_SIZE 30
 
void ErrorHandling(const char* message);
 
int main()
{
    WSADATA wsaData;
    SOCKET hServSock, hClntSock;
    SOCKADDR_IN servAddr, clntAddr;
    int strLen = 0;
 
    int szClntAddr;
    char message[] = "Hello World!";
    
    if (0 != WSAStartup(MAKEWORD(22), &wsaData))
    {
        ErrorHandling("WSAStartup() error!");
    }
 
    hServSock = socket(PF_INET, SOCK_STREAM, 0);
    if (INVALID_SOCKET == hServSock)
        ErrorHandling("socket() error");
 
    memset(&servAddr, 0sizeof(servAddr));
    servAddr.sin_family = AF_INET;
    servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servAddr.sin_port = htons(atoi("8888"));
 
    if (SOCKET_ERROR == bind(hServSock, (SOCKADDR*)&servAddr, sizeof(servAddr)))
    {
        ErrorHandling("bind error \n");
    }
 
    if(SOCKET_ERROR == listen(hServSock, 5))
    {
        ErrorHandling("listen error \n");
    }
 
    szClntAddr = sizeof(clntAddr);
    int i = 0;
    while(true)
    {
        hClntSock = accept(hServSock, (SOCKADDR*)&clntAddr, &szClntAddr);
        if (-1 == hClntSock)
        {
            ErrorHandling("accept() error \n");
        }
        else
        {
            printf("Connected clinet : %d \n", i + 1);
        }
        ++i;
        Sleep(1000);
 
        send(hClntSock, message, BUF_SIZE, 0);
 
        closesocket(hClntSock);
    }
    
    closesocket(hServSock);
    WSACleanup();
 
    return 0;
}
 
void ErrorHandling(const char* message)
{
    fputs(message, stderr);
    fputc('\n', stderr);
    exit(1);
}
cs


<Client>

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
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <ws2tcpip.h>
#include <windows.h>
 
#define BUF_SIZE 30
void ErrorHandling(const char* message);
 
int main()
{
    WSADATA wsaData;
    SOCKET hSocket;
    SOCKADDR_IN servAddr;
    char message[30];
    int strLen;
 
    if (0 != WSAStartup(MAKEWORD(22), &wsaData))
    {
        ErrorHandling("WSAStartup() error!");
    }
 
    hSocket = socket(PF_INET, SOCK_STREAM, 0);
    if (INVALID_SOCKET == hSocket)
    {
        ErrorHandling("WSAStartup() error!");
    }
    
    memset(&servAddr, 0sizeof(servAddr));
    servAddr.sin_family = AF_INET;
    //servAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    inet_pton(AF_INET, "127.0.0.1"&servAddr.sin_addr);
    servAddr.sin_port = htons(atoi("8888"));
 
    if(SOCKET_ERROR == connect(hSocket, (SOCKADDR*)&servAddr, sizeof(servAddr)))
    {
        printf("error:%d \n", WSAGetLastError());
        ErrorHandling("connect() error");
    }
    else
    {
        puts("Connected......");
    }
    
    int beginTime = GetTickCount();        
    strLen = recv(hSocket, message, BUF_SIZE - 10);
    int endTime = GetTickCount();
    int passTime = endTime - beginTime;
    message[strLen] = 0;
    printf("Message from server ms:%d second:%f message:%s \n", passTime, (passTime * 0.001), message);
 
    closesocket(hSocket);
    WSACleanup();        
 
    system("pause");
    return 0;
}
 
void ErrorHandling(const char* message)
{
    fputs(message, stderr);
    fputc('\n', stderr);
    exit(1);
}
cs


<결과>

서버는 1초짜리 일을 했지만 접속순서대로 차례대로 일을 처리했기 때문에,

후순위로 Connect한 클라이언트는 5~6초나 지나서 결과를 받았다.

멀티스레드 서버를 사용해야하는 이유다.

 


Post

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
// ConsoleApplication2.cpp: 콘솔 응용 프로그램의 진입점을 정의합니다.
//
 
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#include <ws2tcpip.h>
 
void ErrorHandling(const char* message);
 
int main()
{
    WSADATA wsaData;
    SOCKET hSocket;
    SOCKADDR_IN servAddr;
    char message[30];
    int strLen;
 
    if (0 != WSAStartup(MAKEWORD(22), &wsaData))
    {
        ErrorHandling("WSAStartup() error!");
    }
 
    hSocket = socket(PF_INET, SOCK_STREAM, 0);
    if (INVALID_SOCKET == hSocket)
    {
        ErrorHandling("WSAStartup() error!");
    }
 
    memset(&servAddr, 0sizeof(servAddr));
    servAddr.sin_family = AF_INET;
//    servAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    inet_pton(AF_INET ,"127.0.0.1"&servAddr.sin_addr);
    servAddr.sin_port = htons(atoi("8888"));
 
    if(SOCKET_ERROR == connect(hSocket, (SOCKADDR*)&servAddr, sizeof(servAddr)))
    {
        ErrorHandling("connect() error!");
    }
 
    strLen = recv(hSocket, message, sizeof(message) - 10);
    if (-1 == strLen)
    {
        ErrorHandling("read() error!");
    }
 
    printf("Message from server : %s \n", message);
 
    closesocket(hSocket);
    WSACleanup();        
 
    return 0;
}
 
void ErrorHandling(const char* message)
{
    fputs(message, stderr);
    fputc('\n', stderr);
    exit(1);
 
}
 
 
cs



오류 C4996 'inet_addr': Use inet_pton() or InetPton() instead or define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API 

2017 되면서 inet_pton() 함수를 쓰면 에러가 난다.
메시지에 inet_pton() 함수를 대신 사용하라고 한다.
(_WINSOCK_DEPRECATED_NO_WARNINGS define을 추가하라고 되어있으나 에러가 나서 그냥 inet_pton()함수 사용하기로..)
해결 방법은 헤더에 ws2tcpip.h 를 추가하고 아래와 같이 inet_pton 함수를 사용하면 된다.

#include <ws2tcpip.h>
inet_pton(AF_INET(ipc4주소체계) , ip주소 , 연결할 서버주소 저장 변수);


Post

서버에서 패킷을 받아서 데이터 파서 중 이해가 안가는 부분이 생겼다.
문자열 배열이 있을 때 2Byte씩 파싱하는 중이었다.
그런데 2byte 파싱한 데이터가 결과가 내 예상과는 달랐다.
확인한 데이터는 배열 0번째는 154, 배열 1번째는 8이었다.

예시소스코드
unsigned char tempString[2];
tempString[0] = 154;
tempString[1] = 8;
unsigned short data;
memcpy(&data, tempString, 2);

154는 2진수로 10011010
8은 2진수로 1000
결과는 10011010 1000 = 100110101000 = 2472인 줄 알았다
그런데 값이 안맞아서 확인해보니
tempString[0]이 0번째이므로 0~255값을 나타냈기 때문에 뒤로 가야한다.
그래서 10011010 1000 자리를 바꿔줘서 합쳐줬더니 알맞은 값이 나온다.
1000 10011010 100010011010 = 2202

▲ top