^(코딩캣)^ = @"코딩"하는 고양이;
썸네일 이미지
[Xcode 오류 해결] Unable to log in with account '<Apple ID>'.
상황 Xcode로 소스 코드를 실행하는데 다음과 같은 오류가 나타난다. No signing certificate "Mac Developer" found. No "Mac Development" signing certificate matching team ID "XXXXXXXXXX" with a private key was found. The operation couldn't be completed. Unable to log in with account ''. The login details for account '' were rejected. Xcode Apple ID 로그인 오류 이런 오류가 뜨는 이유에는 여러가지가 있겠으나 이번 경우에는 Apple ID 로그인에 실패한 경우였다. 최근에 Apple ID..
API/Cocoa
2020. 4. 8. 16:17

[Xcode 오류 해결] Unable to log in with account '<Apple ID>'.

API/Cocoa
2020. 4. 8. 16:17

상황


Xcode로 소스 코드를 실행하는데 다음과 같은 오류가 나타난다.

No signing certificate "Mac Developer" found. No "Mac Development" signing certificate matching team ID "XXXXXXXXXX" with a private key was found.
The operation couldn't be completed. Unable to log in with account '<Apple ID>'. The login details for account '<Apple ID>' were rejected.
Xcode Apple ID 로그인 오류

이런 오류가 뜨는 이유에는 여러가지가 있겠으나 이번 경우에는 Apple ID 로그인에 실패한 경우였다. 최근에 Apple ID의 패스워드를 변경한 적이 있었는데, Xcode는 이전 암호로 로그인을 시도했기 때문에 Code Signing이 되지 않은 것이었다.

 

해결


[Xcode] 메뉴 옆 [Preferences...]를 클릭하여 환경 설정을 연다.

[Xcode] -> Preferences...

[Accounts]를 클릭하면 해당 Apple ID가 세션 만료된 것을 확인할 수 있다. 새로운 암호로 로그인하면 해결 완료.

암호가 바뀌어 세션 연장이 안 된 상태
카테고리 “API/Cocoa”
more...
썸네일 이미지
[BSD Socket] FreeBSD(+*nix) 버전 IPC 클라이언트측 코드
BSD Socket 사용법 정리 FreeBSD(+*nix) 버전 클라이언트측 코드 본 포스팅에서는 FreeBSD를 포함하여 *nix를 기준으로 한 IPC Socket 클라이언트측 코드의 사용 예를 정리한다. 전체 코드 먼저 전체적인 코드를 훑어본다. /* 표준 헤더 include */ #include // intptr_t #include // exit() #include // printf(), sprintf() #include // assert() #include // strerror() #include // errno /* 유닉스 헤더 include */ #include // pthread_create(), pthread_exit(), pthread_cleanup_push(), pthread_clean..
BSD Socket
2020. 4. 8. 16:05

[BSD Socket] FreeBSD(+*nix) 버전 IPC 클라이언트측 코드

BSD Socket
2020. 4. 8. 16:05

BSD Socket 사용법 정리


FreeBSD(+*nix) 버전 클라이언트측 코드


본 포스팅에서는 FreeBSD를 포함하여 *nix를 기준으로 한 IPC Socket 클라이언트측 코드의 사용 예를 정리한다.

 

전체 코드


먼저 전체적인 코드를 훑어본다.

/* 표준 헤더 include */
#include <stdint.h> // intptr_t
#include <stdlib.h> // exit()
#include <stdio.h> // printf(), sprintf()
#include <assert.h> // assert()
#include <string.h> // strerror()
#include <errno.h> // errno

/* 유닉스 헤더 include */
#include <pthread.h> // pthread_create(), pthread_exit(), pthread_cleanup_push(), pthread_cleanup_pop()
#include <strings.h> // bzero()
#include <unistd.h> // ssize_t, read(), write()

/* 소켓 헤더 include */
#include <arpa/inet.h> // htons()
#include <sys/types.h> // socket
#include <sys/socket.h> // socket
#include <sys/un.h> // struct sockaddr_un

#define SCK_FILE "/tmp/codingcat.ipc"
#define SCK_BUFF 512
#define SCK_MESG "Hello, IPC Server!"

void cleanup_routine(void * pfdclient); // 소켓 함수 실행 중 오류가 발생할 때 수행할 공통의 해제 작업이 기술된 함수이다.

int main(void) {
	pthread_t thself; // 현재 실행중인 스레드 번호를 보관한다.

	int fdserver; // 서버에 연결하는 소켓에 대한 파일 디스크럽터.
	socklen_t cbaddrserver; // 서버측 인터넷 주소의 길이를 보관한다.
	struct sockaddr_in addrserver; // 서버측 인터넷 주소를 보관한다.
	int sockresult; // 소켓 함수의 실행 결과를 보관한다.

	size_t cbbuffserver, cbbuffclient; // 서버에서 클라이언트로, 클라이언트에서 서버로 송수신하는 문자열의 길이를 보관한다.
	char buffserver[SCK_BUFF], buffclient[SCK_BUFF]; // 서버에서 클라이언트로, 클라이언트에서 서버로 송수신하는 문자열을 보관한다.
	ssize_t rwresult; // 서버와 클라이언트간 송수신된 문자열의 길이를 보관한다.

	thself = pthread_self(); // 현재 실행중인 스레드 번호를 가져온다.
	pthread_cleanup_push(cleanup_routine, &fdserver);
	
	fdserver = socket(AF_UNIX, SOCK_STREAM, 0);
	if (fdserver < 0) {
		printf("[FAILURE] socket(): %d(%s) @ pthread_t = %p\n", errno, strerror(errno), thself);
		pthread_exit((void *)((intptr_t)errno));
	}
	printf("[SUCCESS] socket() @ pthread_t = %p\n", thself);

	cbaddrserver = sizeof(struct sockaddr_un);
    bzero(&addrserver, cbaddrserver);
    addrserver.sun_family = AF_UNIX;
	strncpy(addrserver.sun_path, SCK_FILE, (sizeof(addrserver.sun_path) / sizeof(addrserver.sun_path[1])));

	sockresult = connect(fdserver, (struct sockaddr *)&addrserver, cbaddrserver);
	if (sockresult < 0) {
		printf("[FAILURE] connect(): %d(%s) @ pthread_t = %p\n", errno, strerror(errno), thself);
		pthread_exit((void *)((intptr_t)errno));
	}
	printf("[SUCCESS] connect() @ pthread_t = %p\n", thself);

	cbbuffserver = sizeof(buffserver);
	bzero(buffserver, cbbuffserver);

	rwresult = read(fdserver, buffserver, cbbuffserver);
	cbbuffserver = strlen(buffserver) * sizeof(char);
	if (rwresult < 0) {
		printf("[FAILURE] read(): %d(%s) @ pthread_t = %p\n", errno, strerror(errno), thself);
		pthread_exit((void *)((intptr_t)errno));
	}
	printf("[SUCCESS] read(): %zd byte(s) @ pthread_t = %p\n", rwresult, thself);
	printf(">> %s\n", buffserver);

	cbbuffclient = sizeof(buffclient);
	bzero(buffclient, cbbuffclient);
	sprintf(buffclient, "%s @ pthread_t = %p", SCK_MESG, thself);

	cbbuffclient = strlen(buffclient) * sizeof(char);
	rwresult = write(fdserver, buffclient, cbbuffclient);
	if (rwresult < 0) {
		printf("[FAILURE] write(): %d(%s) @ pthread_t = %p\n", errno, strerror(errno), thself);
		pthread_exit((void *)((intptr_t)errno));
	}
	printf("[SUCCESS] write(): %zd byte(s) @ pthread_t = %p\n", rwresult, thself);
	printf("<< %s\n", buffclient);
	
	pthread_exit((void *)((intptr_t)0));
	pthread_cleanup_pop(0);
	
	return 0;
}

void cleanup_routine(void * pfdsocket) {
	pthread_t thself;

	int fdsocket;
	int sockresult;

	fdsocket = *((int *)pfdsocket);
	thself = pthread_self();

	if (fdsocket) {
		sockresult = close(fdsocket);
		if (sockresult < 0) {
			printf("[FAILURE] close(): %d(%s) @ pthread_t = %p\n", errno, strerror(errno), thself);
		}
		printf("[SUCCESS] close() @ pthread_t = %p\n", thself);
	}

	return;
}

실행 결과 보기


위 소스 코드를 FreeBSD에서는 다음과 같이 컴파일한 후 실행할 수 있다.

$ cc 소스파일.c -o출력파일 -lpthread

pthread 함수를 사용하기 위한 옵션으로 특별히 -lpthread가 추가되었다. 이 옵션이 없다면, pthread 함수를 호출하는 부분에서 '정의되지 않은 식별자' 오류를 낼 것이다.

서버 접속에 성공하면 다음과 같이 서버로부터 메시지를 수신한다. 여기서 0x800681500은 이 클라이언트와 통신하고 있는 서버 측 thread ID이다.

서버와 문자열 교환에 성공하였을 때 서버측에서 보낸 메시지가 출력된다.

카테고리 “BSD Socket”
more...
썸네일 이미지
[BSD Socket] FreeBSD(+*nix) 버전 IPC 서버측 코드
BSD Socket 사용법 정리 FreeBSD(+*nix) 버전 IPC 서버측 코드 본 포스팅에서는 FreeBSD를 포함하여 *nix를 기준으로 한 IPC Socket 서버측 코드의 사용 예를 정리한다. 전체 코드 먼저 전체적인 코드를 훑어본다. /* 표준 헤더 include */ #include // intptr_t #include // exit() #include // printf(), sprintf() #include // assert() #include // errno #include // strerror() /* 유닉스 헤더 include */ #include // pthread_create(), pthread_exit(), pthread_cleanup_push(), pthread_cleanup..
BSD Socket
2020. 4. 8. 16:05

[BSD Socket] FreeBSD(+*nix) 버전 IPC 서버측 코드

BSD Socket
2020. 4. 8. 16:05

BSD Socket 사용법 정리


FreeBSD(+*nix) 버전 IPC 서버측 코드


본 포스팅에서는 FreeBSD를 포함하여 *nix를 기준으로 한 IPC Socket 서버측 코드의 사용 예를 정리한다.

 

전체 코드


먼저 전체적인 코드를 훑어본다.

/* 표준 헤더 include */
#include <stdint.h> // intptr_t
#include <stdlib.h> // exit()
#include <stdio.h> // printf(), sprintf()
#include <assert.h> // assert()
#include <errno.h> // errno
#include <string.h> // strerror()

/* 유닉스 헤더 include */
#include <pthread.h> // pthread_create(), pthread_exit(), pthread_cleanup_push(), pthread_cleanup_pop()
#include <strings.h> // bzero()
#include <unistd.h> // ssize_t, read(), write()

/* Socket */
#include <arpa/inet.h> // htons()
#include <sys/types.h> // socket
#include <sys/socket.h> // socket
#include <sys/un.h> // struct sockaddr_un

#define SCK_FILE "/tmp/codingcat.ipc"
#define SCK_BUFF 512
#define SCK_MESG "Hello, IPC Client!"

void * start_routine(void * pfdclient); // 클라이언트가 접속할 때마다 새 스레드를 생성하여 실행할 함수이다.
void cleanup_routine(void * pfdsocket); // 소켓 함수 실행 중 오류가 발생할 때 수행할 공통의 해제 작업이 기술된 함수이다.

int main(void) {
	pthread_t thself; // 현재 실행중인 스레드 번호를 보관한다.

	int fdserver, fdclient; // 서버 소켓 및 클라이언트 소켓에 대한 파일 디스크럽터이다.
	socklen_t cbaddrserver, cbaddrclient; // 서버 및 클라이언트에 대한 인터넷 주소의 길이를 보관한다.
	struct sockaddr_un addrserver, addrclient; // 서버 및 클라이언트에 대한 인터넷 주소를 보관한다.
	int sockresult; // 소켓 함수의 실행 결과를 보관한다.

	thself = pthread_self(); // 현재 실행중인 자기 자신의 스레드 번호를 가져온다.
	pthread_cleanup_push(cleanup_routine, &fdclient); // 소켓 함수 실행 중 오류가 발생하였을 때 cleanup_routine을 실행한다.
	
    /* 서버 측 소켓을 생성한다. */
	fdserver = socket(AF_UNIX, SOCK_STREAM, 0);
	if (fdserver < 0) {
    	// 서버 측 소켓 생성에서 오류가 발생하면, errno를 출력한다.
		printf("[FAILURE] socket(): %d(%s) @ pthread_t = %p\n", errno, strerror(errno), thself);
        // cleanup_routine(errno)를 실행한 뒤 본 스레드를 종료한다.
		pthread_exit((void *)((intptr_t)errno));
	}
	printf("[SUCCESS] socket() @ pthread_t = %p\n", thself);

	/* 외부에서 연결할 수 있는 대상 프로세스의 접속 포인트를 구성한다. */
	cbaddrserver = sizeof(struct sockaddr_un); // 프로세스 주소의 길이를 구한다.
    bzero(&addrserver, cbaddrserver); // sockaddr_un 구조체의 내용을 0으로 리셋한다.
    addrserver.sun_family = AF_UNIX; // 구조체 내용 구성 - 1. 주소가 IPC 주소이다.
	strncpy(addrserver.sun_path, SCK_FILE, (sizeof(addrserver.sun_path) / sizeof(addrserver.sun_path[1]))); // 구조체 내용 구성 - 2. IPC로 접속할 수 있는 파일의 주소를 복사한다.

	/* 앞서 구성한 구조체로 서버용 소켓에 바인딩한다. */
	sockresult = bind(fdserver, (struct sockaddr *)&addrserver, cbaddrserver);
	if (sockresult < 0) {
    	// 인터넷 주소 바인딩에서 오류가 발생하면, errno를 출력한다.
		printf("[FAILURE] bind(): %d(%s) @ pthread_t = %p\n", errno, strerror(errno), thself);
        // cleanup_routine(errno)를 실행한 뒤 본 스레드를 종료한다.
		pthread_exit((void *)((intptr_t)errno));
	}
	printf("[SUCCESS] bind() @ pthread_t = %p\n", thself);

	/* 연결 요청을 수용하기 위한 대기열을 구성한다. */
	sockresult = listen(fdserver, SOMAXCONN);
	if (sockresult < 0) {
		// 대기열 구성에서 오류가 발생하면, errno를 출력한다.
		printf("[FAILURE] listen(): %d(%s) @ pthread_t = %p\n", errno, strerror(errno), thself);
        // cleanup_routine(errno)를 실행한 뒤 본 스레드를 종료한다.
		pthread_exit((void *)((intptr_t)errno));
    }
	printf("[SUCCESS] listen() @ pthread_t = %p\n", thself);

	while (1) {
		pthread_t thclient;
		int thresult;

		printf("SERVER WAITING...\n");

		cbaddrclient = sizeof(struct sockaddr_un); // 클라이언트 측 인터넷 주소의 길이를 구한다.
		bzero(&addrclient, cbaddrclient); // sockaddr_in 구조체의 내용을 0으로 리셋한다.

		/* 클라이언트 측의 연결 요청이 있을 때까지 무한정 기다린다. */
		fdclient = accept(fdserver, (struct sockaddr *)&addrclient, &cbaddrclient);
		if (fdclient < 0) {
        	// 연결 대기에서 오류가 발생하면, errno를 출력한다.
			printf("[FAILURE] accept(): %d(%s) @ pthread_t = %p\n", errno, strerror(errno), thself);
            // 연결 대기 다시 한다(무한루프).
			continue;
        }
		printf("[SUCCESS] accept() @ pthread_t = %p\n", thself);

		// 클라이언트 연결이 확인되면, 후속 작업은 새 스레드에 맡긴다. (본 스레드는 연결 대기만 함)
		thresult = pthread_create(&thclient, NULL, start_routine, &fdclient);
		if (thresult < 0) {
        	// 새 스레드 생성에서 오류가 발생하면, errno를 출력한다.
			printf("[FAILURE] pthread_create(): %d(%s) @ pthread_t = %p\n", errno, strerror(errno), thself);
            // 연결 대기 다시 한다(무한루프).
			continue;
		}
		printf("[SUCCESS] pthread_create() -> %p @ pthread_t = %p\n", thclient, thself);
	}

	/* 위 루프가 무한루프이므로 이 이하는 직접 실행될 일은 없으나 형식적으로 적기만 함. */
	pthread_exit((void *)((intptr_t)errno)); // 현재 errno를 리턴하며 본 스레드 종료

	pthread_cleanup_pop(0); // pthread_cleanup_push를 실행했으면 이것을 실행하며 짝을 맞춘다.

	return 0;
}

/* 
 * 새 스레드가 생성되면서 호출될 함수이다. 
 * pdfclient : 클라이언트 측 소켓에 대한 파일 디스크럽터이다.
 */
void * start_routine(void * pfdclient) {
	pthread_t thself;  // 새 스레드의 번호를 보관한다.

	int fdclient; // 클라이언트 측 소켓에 대한 파일 디스크럽터를 보관한다.
	int sockresult; // 소켓 함수 실행 결과를 보관한다.

	size_t cbbuffserver, cbbuffclient; // 서버에서 클라이언트로 보내는 문자열의 길이와 클라이언트에서 서버로 수신된 문자열의 길이를 보관한다.
	char buffserver[SCK_BUFF], buffclient[SCK_BUFF]; // 서버에서 클라이언트로 보내는 문자열과 클라이언트에서 서버로 수신된 문자열을 보관한다.
	ssize_t rwresult; // 송수신한 결과(바이트 수)를 보관한다.

	fdclient = *((int *)pfdclient); // 지정된 주소에서 클라이언트 파일 디스크럽터를 복사해 온다.

	thself = pthread_self(); // 현재 실행 중인 스레드 번호를 가져온다.
	pthread_cleanup_push(cleanup_routine, pfdclient); // 소켓 함수에 오류가 발생했을 때 cleanup_routine을 호출한다.

	/* 서버에서 클라이언트로 보낼 문자열을 구성한다. 서버의 현 스레드 번호를 문자열로 알려준다. */
	cbbuffserver = SCK_BUFF * sizeof(char);
	bzero(buffserver, cbbuffserver);
	sprintf(buffserver, "%s @ pthread_t = %p", SCK_MESG, thself);

	/* 서버에서 클라이언트로 문자열을 보낸다. */
	cbbuffserver = strlen(buffserver) * sizeof(char);
	rwresult = write(fdclient, buffserver, cbbuffserver);
	if (rwresult < 0) {
		// 송신에서 오류가 발생하면, errno를 출력한다.
		printf("[FAILURE] write(): %d(%s) @ pthread_t = %p\n", errno, strerror(errno), thself);
        // cleanup_routine(errno)를 실행한 뒤 본 스레드를 종료한다.
		pthread_exit((void *)((intptr_t)errno));
	}
	printf("[SUCCESS] write(): %zd byte(s) @ pthread_t = %p\n", rwresult, thself);
	printf(">> %s\n", buffserver);

	/* 클라이언트로부터 문자열을 수신할 버퍼를 구성한다. */
	cbbuffclient = SCK_BUFF * sizeof(char);
	bzero(buffclient, cbbuffclient);

	/* 클라이언트로부터 문자열을 받는다. */
	rwresult = read(fdclient, buffclient, cbbuffclient);
	cbbuffclient = strlen(buffclient) * sizeof(char);
	if (rwresult < 0) {
		// 수신에서 오류가 발생하면, errno를 출력한다.
		printf("[FAILURE] read(): %d(%s) @ pthread_t = %p\n", errno, strerror(errno), thself);
        // cleanup_routine(errno)를 실행한 뒤 본 스레드를 종료한다.
		pthread_exit((void *)((intptr_t)errno));
	}
	printf("[SUCCESS] read(): %zd byte(s) @ pthread_t = %p\n", rwresult, thself);
	printf(">> %s\n", buffclient);

	pthread_exit((void *)((intptr_t)0)); // 현재 errno를 리턴하며 본 스레드 종료
	pthread_cleanup_pop(0); // pthread_cleanup_push를 실행했으면 이것을 실행하며 짝을 맞춘다.

	return (void *)((intptr_t)errno);
}

/*
 * 소켓 함수에 오류가 발생했을 경우 수행할 공통의 정리 작업이다.
 * pfdsocket : 오류가 발생하여 닫아야 할 소켓이다.
 */
void cleanup_routine(void * pfdsocket) {
	pthread_t thself;

	int fdsocket;
	int sockresult;

	assert(pfdsocket != NULL);
	fdsocket = *((int *)pfdsocket); // 지정된 주소에서 서버 또는 클라이언트 소켓 파일 디스크럽터를 복사해 온다.
	thself = pthread_self(); // 현재 실행중인 스레드 번호를 가져온다.

	if (fdsocket >= 0) {
    	/* 소켓을 닫는다. */
		sockresult = close(fdsocket);
		if (sockresult < 0) {
			// 소켓 닫기에서 오류가 발생하면, errno를 출력한다.
			printf("[FAILURE] close(): %d(%s) @ pthread_t = %p\n", errno, strerror(errno), thself);
		}
		printf("[SUCCESS] close() @ pthread_t = %p\n", thself);
	}

	return;
}

실행 결과 보기


위 소스 코드를 FreeBSD에서는 다음과 같이 컴파일한 후 실행할 수 있다.

$ cc 소스파일.c -o출력파일 -lpthread

pthread 함수를 사용하기 위한 옵션으로 특별히 -lpthread가 추가되었다. 이 옵션이 없다면, pthread 함수를 호출하는 부분에서 '정의되지 않은 식별자' 오류를 낼 것이다.

클라이언트로부터 연결을 기다리고 있는 IPC 서버 프로그램.

ID가 0x800681000인 thread가 무한루프를 돌리며 접속을 기다리다가 클라이언트로부터 접속이 발생하면 새 thread를 생성되면서 해당 클라이언트와 통신하게 된다. 여기서는 0x800681000로부터 0x800681500가 파생되고, 0x800681500를 통해 클라이언트가 통신한다. 이 과정은 다음과 같이 화면으로 출력된다.

클라이언트로부터 접속이 발생할 때마다 새 thread를 생성하여 통신한다.

IPC 서버 프로그램을 실행한 후에는 다음과 같이 소켓으로 지정한 경로에 파일이 생성된 것을 확인할 수가 있다.

$ ls -al | grep 파일이름

해당 경로에 실제로 임시 파일이 생성되었음을 확인할 수 있다.

카테고리 “BSD Socket”
more...

“2020/04” (3건)