251018

lililllilillll·2025년 10월 18일

개발 일지

목록 보기
328/350

✅ 한 것들


  • 윤성우의 열혈 TCP/IP 소켓 프로그래밍
  • R&D : Flat kit


📖 윤성우의 열혈 TCP/IP 소켓 프로그래밍


10-4 멀티태스킹 기반의 다중 접속 서버

클라가 연결요청 할 때마다 에코 서버가 자식 프로세스 생성해서 서비스 제공

  • 1 : 에코 서버가 accept()로 연결 요청 수락
  • 2 : 소켓 파일 디스크립터를 자식 프로세스 생성해서 넘겨준다
  • 3 : 자식 프로세스는 전달받은 파일 디스크립터로 서비스 제공
int main(int argc, char *argv[])
{
	int serv_sock, clnt_sock;
	struct sockaddr_in serv_adr, clnt_adr;

	pid_t pid;
	struct sigaction act;
	socklen_t adr_sz;
	int str_len, state;
	char buf[BUF_SIZE];
	if(argc!=2) {
		printf("Usage : %s <port>\n", argv[0]);
		exit(1);
	}

	act.sa_handler=read_childproc;
	sigemptyset(&act.sa_mask);
	act.sa_flags=0;
	state=sigaction(SIGCHLD, &act, 0);
	serv_sock=socket(PF_INET, SOCK_STREAM, 0);
	memset(&serv_adr, 0, sizeof(serv_adr));
	serv_adr.sin_family=AF_INET;
	serv_adr.sin_addr.s_addr=htonl(INADDR_ANY);
	serv_adr.sin_port=htons(atoi(argv[1]));

	if(bind(serv_sock, (struct sockaddr*) &serv_adr, sizeof(serv_adr))==-1)
		error_handling("bind() error");
	if(listen(serv_sock,5)==-1)
		error_handling("listen() error");

	while(1)
	{
		adr_sz=sizeof(clnt_adr);
		clnt_sock=accept(serv_sock, (struct sockaddr*)&clnt_adr, &adr_sz);
		if(clnt_sock==-1)
			continue;
		else
			puts("new client connected...");
		pid=fork();
		if(pid==-1)
		{
			close(clnt_sock);
			continue;
		}
		if(pid==0) // 자식 프로세스 실행 영역
		{
			close(serv_sock);
			while((str_len=read(clnt_sock,buf,BUF_SIZE))!=0)
				write(clnt_sock, buf, str_len);

			close(clnt_sock);
			puts("client disconnected...");
			return 0;
		}
		else
			close(clnt_sock);
	}
	close(serv_sock);
	return 0;
}

void read_childproc(int sig)
{
	pid_t pid;
	int status;
	pid=waitpid(-1, &status, WNOHANG);
	printf("removed proc id: %d \n", pid);
}

이제 여러 클라 접속 가능해진다

fork()하면 소켓은 하나지만 연결된 파일 디스크립터가 하나 더 생긴다.
부모 프로세스에선 새로 만들어진 클라 소켓 파일 디스크립터 필요 없으니까 닫고,
자식 프로세스에선 서버 소켓 파일 디스크립터 필요 없으니까 닫는다
안 닫고 냅두면 나중에 하나만 지워도 소켓 소멸이 안됨

10-5 TCP의 입출력 루틴(Routine) 분할

기존 에코 클라 : 데이터 전송 후 돌아올 때까지 데이터 입력 못 함
fork() 이용하면 데이터 송신과 수신 분리 가능

이렇게 프로세스에서 루틴을 분리하면 코드 구현이 수월해진다.
(에코 클라는 루틴 분리할 근거가 있진 않고, 예시로 구현해보는거)

	pid=fork();
	if(pid==0)
		write_routine(sock,buf);
	else
		read_routine(sock,buf);

	close(sock);
	return 0;
}

void read_routine(int sock, char *buf)
{
	while(1)
	{
		int str_len=read(sock, buf, BUF_SIZE);
		if(str_len==0)
			return;

		buf[str_len]=0;
		printf("Message from server: %s", buf);
	}
}
void write_routine(int sock, char *buf)
{
	while(1)
	{
		fgets(buf, BUF_SIZE, stdin);
		if(!strcmp(buf,"q\n") || !strcmp(buf,"Q\n"))
		{
			shutdown(sock, SHUT_WR);
			return;
		}
		write(sock, buf, strlen(buf));
	}
}


🛠️ R&D


Flat kit

Stylized Surface

  • material shader 중에 Flat Kit 카테고리 아래에 머테리얼들 있다
  • extra cel layer, specular 같은 기능들 켜면 shader variant 만들어지니까 꼭 필요한 것만 켜라
  • Rim만으로도 다양한 효과 줄 수 있다.
  • normal이 flat-shaded면 edge size 조절할 때 그림자가 네모꼴로 생성됨
  • 외곽선 셰이더 : Stylized Surface with Outline, Outline Image Effect
  • 멋진 전환 효과 : Cel layer size, Specular size, Rim size를 animate
  • Gradient 생성 : Cel Shading Mode > Curve, Enable Height Gradient
  • Vertex Color : 메시의 vertex color value를 곱한다. 디버그용.
  • Outline 켜면 Renderer에 Renderer Feature 생긴다.
    • Outline 끌 때 자동으로 지워지지만, 안 지워질수도 있으니 렌더러 확실하게 체크해라
    • Advanced Settings
      • Event : 프레임 어느 시점에 렌더링 될지
      • Filters : 어떤 오브젝트가 렌더될지
      • Overrides : 렌더링 어느 부분 override 할 건지
  • Outline에 gap 생기면
    • 방법 1 : 모델 노말 수정
    • 방법 2 : Smooth Normals 옵션 켜기. 모델 수정해버리니까 백업. (근데 안 유용한듯 이거)
    • 방법 3 : mesh의 Import Settings > Normals > Calculate 변경 > Smoothing Angle 증가 > (외곽선 더러운거 지우려면) material의 Depth Offset 조정
    • 방법 4 : outline의 width 줄이고 scale 키운다


profile
너 정말 **핵심**을 찔렀어

0개의 댓글