251006

lililllilillll·2025년 10월 6일

개발 일지

목록 보기
316/350

✅ 한 것들


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


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


Chapter 06 UDP 기반 서버/클라이언트

06-1 UDP에 대한 이해

  • TCP와 달리 흐름제어를 하지 않는다
  • 호스트로 수신된 패킷을 PORT 정보를 참조하여 최종 목적지인 UDP 소켓에 전달한다
  • UDP도 나름 신뢰할 만 하다. 잠깐의 화면 떨림, 잡음 정도 괜찮으면 사용.

06-2 UDP 기반 서버/클라이언트의 구현

  • UDP의 서버와 클라는 연결돼있지 않다
  • UDP에선 서버건 클라건 소켓 하나만 있으면 여러 호스트와 통신 가능

TCP는 소켓 생성 후 데이터 전송 시에 주소 정보 따로 추가 안 한다.
하지만 UDP는 연결상태 유지하지 않으므로 데이터 전송마다 목적지 주소정보 추가 필요.

  • sendto() : 주소정보를 써 넣으면서 데이터를 전송
  • recvfrom() : UDP 데이터 수신. 발신지 정보를 함께 반환.
int main(int argc, char *argv[])
{
	int serv_sock;
	char message[BUF_SIZE];
	int str_len;
	socklen_t clnt_adr_sz;

	struct sockaddr_in serv_adr, clnt_adr;
	if(argc != 2) {
		printf("Usage : %s <port>\n", argv[0]);
		exit(1);
	}

	serv_sock=socket(PF_INET, SOCK_DGRAM, 0);
	if(serv_sock == -1)
		error_handling("UDP socket creation error");

	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");

	while(1)
	{
		clnt_adr_sz=sizeof(clnt_adr);
		str_len=recvfrom(serv_sock,message,BUF_SIZE,0,
		   (struct sockaddr*)&clnt_adr, &clnt_adr_sz);
		sendto(serv_sock, message, str_len, 0,
	 	(struct sockaddr*)&clnt_adr, clnt_adr_sz);
	}
	close(serv_sock);
	return 0;
}

uecho_server.c

int main(int argc, char *argv[])
{
	int sock;
	char message[BUF_SIZE];
	int str_len;
	socklen_t adr_sz;

	struct sockaddr_in serv_adr, from_adr;
	if(argc!=3){
		printf("Usage : %s <IP> <port>\n", argv[0]);
		exit(1);
	}

	sock=socket(PF_INET, SOCK_DGRAM, 0);
	if(sock==-1)
		error_handling("socket() error");

	memset(&serv_adr, 0, sizeof(serv_adr));
	serv_adr.sin_family=AF_INET;
	serv_adr.sin_addr.s_addr=inet_addr(argv[1]);
	serv_adr.sin_port=htons(atoi(argv[2]));

	while(1)
	{
		fputs("Insert message(q to quit): ", stdout);
		fgets(message, sizeof(message), stdin);
		if(!strcmp(message, "q\n") || !strcmp(message, "Q\n"))
			break;

		sendto(sock, message, strlen(message), 0,
	 	(struct sockaddr*)&serv_adr, sizeof(serv_adr));
		adr_sz=sizeof(from_adr);
		str_len=recvfrom(sock,message,BUF_SIZE,0,
		   (struct sockaddr*)&from_adr, &adr_sz);
		message[str_len]=0;
		printf("Message from server: %s", message);
	}
	close(sock);
	return 0;
}

uecho_clinet.c

UDP에선 sendto() 호출 전에 bind() 호출해서 주소 정보 할당해야 한다.
sendto() 호출 전까지 주소 정보 할당 안 됐다면 IP와 PORT 번호가 자동으로 할당된다. (일반적 구현법)



⚔️ 프로그래머스


정수 삼각형

int MaxVal(int depth, int idx, vvi &triangle, vvi &dp)
{
    if(dp[depth][idx]!=-1) return dp[depth][idx];
    
    int originVal = triangle[depth][idx];
    if(depth == size(triangle)-1) return originVal;
    
    int leftMax = MaxVal(depth+1, idx, triangle, dp);
    int rightMax = MaxVal(depth+1, idx+1, triangle, dp);
    
    dp[depth][idx] = originVal + max(leftMax,rightMax);
    return dp[depth][idx];
}

int solution(vector<vector<int>> triangle) {
    // 하향식으로 왼쪽, 오른쪽 최대 재귀
    int tri_sz = size(triangle);
    vvi dp = vvi(tri_sz,vi(size(triangle[tri_sz-1]),-1));
    return MaxVal(0,0,triangle,dp);
}

하향식으로 풀었더니 시간 초과됐다.
하향식이나 상향식이나 시간 복잡도 똑같을텐데?

int solution(vector<vector<int>> triangle) {
    int tri_sz = size(triangle);
    if(tri_sz == 1) return triangle[0][0];
    vvi dp = vvi(tri_sz,vi(size(triangle[tri_sz-1]),0));
    
    for(int i=tri_sz-1; 0<i; i--)
    {
        int w = size(triangle[i]);
        for(int j=0; j<w; j++)
        {
            int sendVal = triangle[i][j] + dp[i][j];
            if(j-1 >= 0) dp[i-1][j-1] = max(dp[i-1][j-1],sendVal);
            if(j != w-1)  dp[i-1][j] = max(dp[i-1][j],sendVal);
        }
    }
    
    return dp[0][0]+triangle[0][0];
}

상향식으로 푸니 맞았다고 해줌
다른 풀이 중에 하향식 없는거 보니까
재귀로는 안되게 시간 조건을 빡빡하게 둔듯.

int solution(vector<vector<int>> t) {
    int answer = 0;

    for (int i = t.size() - 1; i > 0 ; i--)
    {
        for (int j = 0; j < t[i].size() - 1; j++)
        {
            if (t[i][j] > t[i][j + 1])
            {
                t[i - 1][j] += t[i][j];
            }
            else
            {
                t[i - 1][j] += t[i][j + 1];
            }
        }
    }

    answer = t[0][0];

    return answer;
}

다른 사람 풀이.
오른쪽을 바로 비교하면서 위를 갱신하면
불필요한 공간이나 코드가 줄어든다.



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

0개의 댓글