MsgSend, MsgReceive, MsgReply를 이용한 client - server sample

MsgSend는 함수명만 보면 보내기만 할것 같지만, 실제로는 받는것도 하고 있다. Client - Server 모델에서 echo 서버 형태를 구현한다고 하면 client쪽에서는 send 이후 receive로 받아오는데, 이때 receive할때까지 client는 기다린다. MsgSend는 send, receive를 합한 형태로 보면 된다. 그렇기 때문에 MsgSend는 데이터를 받아올때까지 Blocking되는 특성이 있다. 함수 원형은 아래와 같다. 

#include <sys/neutrino.h>

int MsgSend (int coid,
             const void *smsg,
             int sbytes,
             void *rmsg,
             int rbytes);

 

coid : ConnectAttach()를 통해서 나온 값

smsg : 보내는 데이터

sbytes : 보내는 데이터의 길이

rmsg : 받는 데이터

rbytes : 받는 데이터의 길이 

 

MsgReceive는 데이터를 받는 함수이고, MsgReply는 응답을 하는 함수이다. sample을 보면 이해가 갈것이다.

//Server.c 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/neutrino.h>

#define EOK 1234
int main(void)
{
    int     rcvid;         // indicates who we should reply to
    int     chid;          // the channel ID
    char    message [512]; // big enough for our purposes

	printf("Server Start\n");

    // create a channel
    chid = ChannelCreate (0);
	printf("Wait in channel %d\n",chid);

    // this is typical of a server:  it runs forever
    while (1) {

        // get the message, and print it
        rcvid = MsgReceive (chid, message, sizeof (message),
                            NULL);
        printf ("Got a message, rcvid is %X\n", rcvid);
        printf ("Message was \"%s\".\n", message);

        // now, prepare the reply.  We reuse "message"
        strcpy (message, "This is the reply");
        MsgReply (rcvid, EOK, message, sizeof (message));
    }

	return 0;
}

서버쪽에서는 ChannelCreate로 chid를 가져오고, Client는 여기에 Attach한다. 

//client.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/neutrino.h>

int main(int argc, char *argv[]){
	char *smsg = "This is the outgoing buffer";
	char rmsg [200];
	int coid;
	int ret;
	pid_t pid;

	if(argc != 2){
		fprintf(stderr,"Usage : %s [server_pid] \n",argv[0]);
		exit(EXIT_FAILURE);
	}
	pid = atoi(argv[1]);
	// establish a connection
	coid = ConnectAttach (0, pid, 1, 0, 0);
	if (coid == -1) {
		fprintf (stderr, "Couldn't ConnectAttach to %d/%d/%d!\n", 0, pid, 1);
		perror (NULL);
		exit (EXIT_FAILURE);
	}

	// send the message
	if ((ret  = MsgSend (coid,
				smsg,
				strlen (smsg) + 1,
				rmsg,
				sizeof (rmsg))) == -1) {
		fprintf (stderr, "Error during MsgSend\n");
		perror (NULL);
		exit (EXIT_FAILURE);
	}

	if (strlen (rmsg) > 0) {
		printf ("Process ID %d returns code :%d, msg :\"%s\"\n", pid, ret, rmsg);
	}
}

 

여기서 ConnectAttach의 channel id는 1로 임의로 지정했는데, argv로 입력받는 것이 더 좋을듯하다. 난 귀찮아서...

반응형
블로그 이미지

REAKWON

와나진짜

,

나의 중이염 일대기

7살, 8살 쯔음 혼자서는 똥, 오줌도 못가릴 무렵, 귀 속이 찢어진 듯한 통증과 함께 진물이 나온 기억이 있는데, 이때 방치했던 것이 만성 중이염으로 이어졌다. 중이염이라는게 콧물 등에 포함된 세균이 유스타키오관을 통해 중이 안으로 침투해 염증을 일으키는 질환으로 진물이 고막 안에 고여있는데, 이때 느낌이 귀에 물이 찬 느낌이다. 그러다가 이게 마침내 터지면 귀에 진물이 나오게 된다. 고막에 구멍이 뚫리니 통증을 당연이 느끼게 되는것이다. 특히 이 유스타키오관이 짧은 어린애들이 잘걸리니 아이들이 아무이유없이 울고있다면 궁디팡하지말고 이비인후과로 데려가도록 하자. 

https://post.naver.com/viewer/postView.nhn?volumeNo=7842154&memberNo=24304009

 

암튼 12살까지 방치하다가 12살~13살까지 동네 이비인후과 병원을 다니기 시작했다. 몇년을 방치하니까 튜브를 삽관하는 수술을 했는데, 이때 삽관이 잘 되지 않아 대학병원에서 수술을 받았다. 14살이 되어서 아주대학교 병원에서 수술을 진행했고 귀 안에 튜브를 박고 1년 동안 통원 치료를 받았는데, 좀 처럼 청력을 돌아오지 않았다. 이렇게 튜브 삽관 수술을 18살때까지 진행하다가 더이상 진전되지 않은 것 같아 21살까지 방치하다가 군대를 가게 되었다.

이때부터는 거의 자포자기다. 청력은 한쪽에만 의지하며 이후 +10년 추가. 합 20년 가까이 중이염을 앓고 지냈는데, 최근 이명과 함께 귀가 먹먹해지는 느낌이 들어 대학 병원이 아닌 귀 전문 병원으로 진료를 받으러갔다. 소리이비인후과가 유명하다고 해서  무려 청담으로 향했다. 1층을 제외한 건물 자체가 병원이다..

 

검사

가게 되면 우선 귀를 한번 째본다. 긴 뾰족한 꼬챙이로 귀의 고막을 한번 뚫는데, 이 이유는 안에 물이 찼는지, 액체형태로 빠져나오는지, 아니면 나오지 않는지 확인해보는 거라고 한다. 난 이 꼬챙이를 대학병원을 다니면서 몇 차례 당한적이 있어 보기만해도 몸에서 경기가 일어났다.

나 : "헑엉 ㅠㅠ 저 이거 안하면 안돼요? 이거 엄청 아픈데...ㅜㅜ "

의사 : "안아프게 할게요. 살짝만"

결국 살짝 뚫었는데, 그렇게 아프게 하지 않았다. 역시 다년간의 경험으로 처음부터 엄살을 떨어야만 의사샘이 살살해준다. 여러분도 일단 개거품부터 물어보자.

나는 진물이 나오지 않았다. 이것은 즉, 고름이 안에 진득진득하게 차있어서 그런것이다. 이제 청력검사를 시행한다. 청력검사는 별거없는데, 삐 소리가 나면 버튼을 누르는 식, 그리고 귀 안에 청신경?이 살아있나 보는 진단을 하게 된다. 별거없으니 패스

나는 고막이 안으로 말려들어간 유착성, 그리고 안에 고름이 차있는 진주종성 중이염 판정을 받고 수술을 하는 것으로 판정이 났다.  수술을 하기위한 피, 소변검사는 소리이비인후과 병원에서 해주는데, 나머지 X-ray 사진, 심전도 검사는 내과에서 하고 팩스로 전달해야한다.

 

입원은 총 아래와 같이 3일하게 된다. 무적권 1인실 밖에 없고, 청담이라 1박에 무려 24만원이다. 시간당 만원꼴.

 

수술은 총 3가지를 진행하는데 아래와 같다.

1. 유양동 절제술

2. 고막 성형술

3. 이소골 재건술

이 수술들을 진행하기 위해서는 귀구멍 안으로 수술하는게 아니라 귀 뒤 절개한 다음 진행해야하는 수술이라 좀 무섭...긴해도 전신마취라서 자고 일어나면 끝나있다... 라고 생각하는게 정신건강에 좋다. 스스로를 가스라이팅하길 바란다. 

이후 2차 수술도 할수도, 안할 수도 있다고 한다. 그건 1차 수술 결과를 보고 알 수 있나보다. 

 

입원(1일차)

드디어 그날이 되어 상큼하게 병원을 가서 접수를 한다. 뭔가 다리가 요염하게 나왔는데, 오줌을 참고 있었나보다. 여기 안내 데스크에 있는 간호사분들은 환자한테 먼저 인사 안하길래 내가 먼저했다. 날 못본거겠지? 그렇다고 내가 10곤대는 아니고... 

 

 

접수하고 나면 코로나 검사를 받고 여기서 대기좀 타야되는데 기다리는 시간동안 만성 중이염에 대해서 알아보자.

 

옼키, 대충 봤으면 이후 어지럼증 검사를 하고 입실하게 된다. 방안의 풍경은 이러하다.

 

 

 

8시까지는 환자가 돌아와야하고, 10시까지만 면회가 허용이 가능하다. 첫날은 저녁이 안나오니까 밖에서 먹고오거나, 싸오거나 해야한다. 오후 9시쯤 되어서 항생제 반응검사를 하고 항생제를 맞는다.

수술 당일(2일차)

나의 경우 수술은 전신마취를 통해서 진행했다. 오전 7시부터 수술실에 들어간것으로 기억하고, 마취전문의를 동반하여 수술을 진행한다. 그렇기 때문에 자고 일어나면 수술이 끝나있다. 아참! 수술 당일에 무조건 보호자가 한명이 필요하다. 

수술이 끝나고  난 후의 모습인데, 미간에 야무지게 인상을 쓰고 있는거보니, 다행히 살아있다. 사진은 내 사랑스러운 여자친구가 찍어주심.. 

 

음.. 이때부터는 이제 통증과의 싸움이긴 한데, 진통제를 맞으면 조금은 괜찮아지긴한다. 근데 아프면 너무 참지말고 진통제를 맞거나 먹는것이 더 좋다. 통증의 정도는 귀를 송곳으로 뚫은 정도의 통증이라고 보면 될것 같다.

수술이 끝난 직후 나의 증상은 몇가지 있었는데 나열하면 아래와 같다.

● 혀가 얼얼하다. 약간 미각이 안느껴진다. 수술후 하루가 지나도 그렇다.

● 목이 아프다. 전신 마취중에 기관지가 손상이 될 수도 있다고하는데, 그런건가보다. 목이 좀 아프다. 

● 어지러움은 없었다. 마취깨고 1시간 지나고 나서야 제정신이 들었다.

● 귀에 물흐는 소리와 물이 차있는 소리, 마치 고막이 움직이는 느낌이 든다. 고막 성형했으니 그런 소리가 나는것은 매우 정상이라한다. 

 

병원밥은 못참지

이 와중에 밥은 레알 맛있는데, 씹기가 어려운게 문제다. 

사진에 보이는거 파란색 머리띠 저게 진짜 답답하긴 한데, 그 안에 거즈로 피를 막아놓고 고정해서 차고 있어야한다. 수술이 7시부터 9시 살짝 넘어서 끝났고, 이 거즈는 세시 정도에 의사샘이 갈아준다. 이때 본인 피 보고 놀라지 마시길...

나같은 경우에는 시간이 지날수록 통증이 좀 심해졌다. 그렇지만 저녁먹고 진통제 맞고, 새벽에 아플때 진통제 먹고 그러니 참을만은 했다.

오늘 하루 종일 나 챙겨주고 간호해준 여자친구, 너한테 평생잘해주께 영원히. 사랑한다 베이비♥♥♥♥

 

퇴원(3일차)

오후 6시에 상처부의를 소독해주고, 거즈대신 살색 의료용 테이프같은거로 갈아준다. 9시에 의사샘이 다시 오시는데, 별건 없다. 어디 불편한지, 아픈지 묻고 퇴원하면 된다. 입원비.. 188만원 나왔다. 18

이제부터 7주일동안은 상처를 잘 아물게 최대한 노력을 해야하는데, 항생제는 식후 30분 3끼 다먹고 소화제도 같이 먹는다. 아플때는 진통제를 먹으면 된다. 나같은 경우에는 하루에 두번 잘 챙겨먹는다. 

사진에서 보면 가장 오른쪽 위에는 귀 외이도에 넣어주는 지혈솜? 같은건데, 새로로 꽂아넣고 살색 테이프로 귀에 붙여줘야 나중에 갈때 편하다. 

 

수술후 주의사항 중에서도 술, 담배는 안되는 것은 다 알고 있겠지만 물을 특히 조심해야한다. 오히려 안씨는것을 추천해줄 정도로 물을 닿게해서는 안된다. 특히 상처부위말고 귀구멍안에 물은 진짜 들어가면 안된다고한다. 조심해야지~~~

여기까지 나의 중이염 수술 과정과 후기를 적었는데, 지금 이 시점은 퇴원하고 막 글을 쓰는 시점이라서 수술 결과는 모른다. 근데 의사샘이 수슬은 잘됐다고 알려주셨는데, 이제 잘 관리하고 2차 후기를 남길 수 있도록 해야지. 이 글을 끝까지 본 사람이면 중이염 수술을 생각하고 있는 분일텐데, 너무 무섭게 생각치 마시고 용기 내서 완치하세요.

반응형
블로그 이미지

REAKWON

와나진짜

,

리눅스에 관한 더 많은 정보와 예제를 담은 리눅스 교재를 배포했습니다. 아래의 페이지에서 리눅스 교재를 받아가세요.

https://reakwon.tistory.com/233

 

리눅스 프로그래밍 note 배포

티스토리에 리눅스에 관한 내용을 두서없이 여지껏 포스팅했었데요. 저도 제 포스팅을 찾기가 어렵기도 하고 티스토리에서 코드삽입을 하게 되면 이게 일자로 쭉 쓰여져있는 x같은 현상이 생겨

reakwon.tistory.com

 

readn, writen

네트워크같은 환경에서 어마어마한 데이터가 쓰여질 경우 일반 read함수로는 전부 읽어올 수 없는 상황이 발생할 수 있습니다. 또 반대의 경우에도 마찬가지입니다. 큰 데이터가 한번에 쓰여질 경우 write함수로는 쓰여지지 않을 수 있습니다. 아래와 같은 두가지의 상황이 발생하기 때문인데요.

1) read 연산이 요청보다 작은 바이트를 되돌려줄 경우에는 이는 오류가 아닙니다. 단지, 더 읽어야할 데이터가 있다는 뜻입니다. 2) write 역시 요청보다 작은 바이트를 돌려줄 수 있는 경우가 있는데, 커널의 출력 버퍼가 꽉 찼을때 이런 경우가 발생합니다.

1), 2)는 어떻게 해결할 수 있을까요? 답은 데이터가 요청된 값이 될때까지 읽거나 쓰는 것입니다. 이런 함수가 아래의 readn, writen 함수입니다.

- 아래의 코드는 Advanced Programming in the UNIX Environment 3판을 참고하여 만든 코드입니다.

 rean 함수

ssize_t readn(int fd, void *data, size_t n){
        size_t left;    //남은 바이트
        size_t read_n;  //읽은 바이트

        left = n;

        while(left > 0){
                if((read_n = read(fd, data, left)) < 0){
                        if(left == n) return -1;
                        else break;
                }else if(read_n == 0) break;
                left -= read_n; //얼마나 남았는지 갱신
                data += read_n; //남은 바이트 읽기 위해 포인터 이동
        }

        return n-left;
}

 

readn 함수를 보면 while문을 통해서 계속 다 읽을때까지 read를 호출하는 것을 볼 수 있습니다. read가 0을 반환하면 다 읽었다고 판단하여 while 루프를 종료하고 빠져나오면 됩니다.

 

writen 함수

ssize_t writen(int fd, const void *data, size_t n){
        size_t left;    //쓰기까지 남은 바이트
        ssize_t written_n;      //쓴 바이트

        left = n;

        while(left > 0){
                if((written_n = write(fd, data, left)) <0){
                        if(left == n) return -1;
                        else break;
                }else if(written_n == 0) break;
                left -= written_n;      //얼마나 남았는지 갱신
                data += written_n;      //남은 바이트 쓰기 위해 포인터 이동
        }

        return n-left;
}

 

writen 함수 역시 계속 data를 쓸때까지 while 루프로 계속 write를 호출하는 것을 볼 수 있습니다. write가 0을 반환하게 되면 다 썼다는 의미로 반복문을 빠져나오고 writen 함수가 종료됩니다.

 

readn, writen 함수는 read, write함수와 동일하게 사용이 가능합니다. 이 함수들은 socket과 같은 네트워크, 파이프, FIFO 등에서 대량의 바이트를 읽거나 쓰기위한 함수라는 것을 기억하시기 바랍니다. 일반 파일 IO에서는 read, write만 사용해도 무관합니다.

반응형
블로그 이미지

REAKWON

와나진짜

,