The basic idea of a message queue is a simple one.
Two (or more) processes can exchange information via access to a common system message queue. The sending process places via some (OS) message-passing module a message onto a queue which can be read by another process (Figure 24.1). Each message is given an identification or type so that processes can select the appropriate message. Process must share a common key in order to gain access to the queue in the first place (subject to other permissions -- see below).
Fig. 24.1 Basic Message Passing IPC messaging lets processes send and receive messages, and queue messages for processing in an arbitrary order. Unlike the file byte-stream data flow of pipes, each IPC message has an explicit length. Messages can be assigned a specific type. Because of this, a server process can direct message traffic between clients on its queue by using the client process PID as the message type. For single-message transactions, multiple server processes can work in parallel on transactions sent to a shared message queue.
Before a process can send or receive a message, the queue must be initialized (through the msgget function see below) Operations to send and receive messages are performed by the msgsnd() and msgrcv() functions, respectively.
When a message is sent, its text is copied to the message queue. The msgsnd() and msgrcv() functions can be performed as either blocking or non-blocking operations. Non-blocking operations allow for asynchronous message transfer -- the process is not suspended as a result of sending or receiving a message. In blocking or synchronous message passing the sending process cannot continue until the message has been transferred or has even been acknowledged by a receiver. IPC signal and other mechanisms can be employed to implement such transfer. A blocked message operation remains suspended until one of the following three conditions occurs:
The msgget() function initializes a new message queue:
int msgget(key_t key, int msgflg)
It can also return the message queue ID (msqid) of the queue corresponding to the key argument. The value passed as the msgflg argument must be an octal integer with settings for the queue's permissions and control flags.
The following code illustrates the msgget() function.
#include <sys/ipc.h>; #include <sys/msg.h>; ... key_t key; /* key to be passed to msgget() */ int msgflg /* msgflg to be passed to msgget() */ int msqid; /* return value from msgget() */ ...key = ...msgflg = ...if ((msqid = msgget(key, msgflg)) == –1) { perror("msgget: msgget failed"); exit(1); } else (void) fprintf(stderr, “msgget succeeded");...
Processes requesting access to an IPC facility must be able to identify it. To do this, functions that initialize or provide access to an IPC facility use a key_t key argument. (key_t is essentially an int type defined in <sys/types.h>
The key is an arbitrary value or one that can be derived from a common seed at run time. One way is with ftok() , which converts a filename to a key value that is unique within the system. Functions that initialize or get access to messages (also semaphores or shared memory see later) return an ID number of type int. IPC functions that perform read, write, and control operations use this ID. If the key argument is specified as IPC_PRIVATE, the call initializes a new instance of an IPC facility that is private to the creating process. When the IPC_CREAT flag is supplied in the flags argument appropriate to the call, the function tries to create the facility if it does not exist already. When called with both the IPC_CREAT and IPC_EXCL flags, the function fails if the facility already exists. This can be useful when more than one process might attempt to initialize the facility. One such case might involve several server processes having access to the same facility. If they all attempt to create the facility with IPC_EXCL in effect, only the first attempt succeeds. If neither of these flags is given and the facility already exists, the functions to get access simply return the ID of the facility. If IPC_CREAT is omitted and the facility is not already initialized, the calls fail. These control flags are combined, using logical (bitwise) OR, with the octal permission modes to form the flags argument. For example, the statement below initializes a new message queue if the queue does not exist.
The msgctl() function alters the permissions and other characteristics of a message queue. The owner or creator of a queue can change its ownership or permissions using msgctl() Also, any process with permission to do so can use msgctl() for control operations.
The msgctl() function is prototypes as follows:
int msgctl(int msqid, int cmd, struct msqid_ds *buf )
The msqid argument must be the ID of an existing message queue. The cmd argument is one of:
IPC_STAT
-- Place information about the status of the queue in the data structure pointed to by buf. The process must have read permission for this call to succeed.
IPC_SET
-- Set the owner's user and group ID, the permissions, and the size (in number of bytes) of the message queue. A process must have the effective user ID of the owner, creator, or superuser for this call to succeed.
IPC_RMID
-- Remove the message queue specified by the msqid argument.
The following code illustrates the msgctl() function with all its various flags:
The msgsnd() and msgrcv() functions send and receive messages, respectively:
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);int msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
The msqid argument must be the ID of an existing message queue. The msgp argument is a pointer to a structure that contains the type of the message and its text. The structure below is an example of what this user-defined buffer might look like:
struct mymsg { long mtype; /* message type */ char mtext[MSGSZ]; /* message text of length MSGSZ */}
The msgsz argument specifies the length of the message in bytes.
The structure member msgtype is the received message's type as specified by the sending process.
The argument msgflg specifies the action to be taken if one or more of the following are true:
The number of bytes already on the queue is equal to msg_qbytes.
The total number of messages on all queues system-wide is equal to the system-imposed limit.
These actions are as follows:
If (msgflg & IPC_NOWAIT) is non-zero, the message will not be sent and the calling process will return immediately.
If (msgflg & IPC_NOWAIT) is 0, the calling process will suspend execution until one of the following occurs:
The condition responsible for the suspension no longer exists, in which case the message is sent.
The message queue identifier msqid is removed from the system; when this occurs, errno is set equal to EIDRM and -1 is returned.
The calling process receives a signal that is to be caught; in this case the message is not sent and the calling process resumes execution.
Upon successful completion, the following actions are taken with respect to the data structure associated with msqid:
msg_qnum is incremented by 1.
msg_lspid is set equal to the process ID of the calling process.
msg_stime is set equal to the current time.
The following code illustrates msgsnd() and msgrcv():
#include <sys/types.h> #include <sys/ipc.h>#include <sys/msg.h>...int msgflg; /* message flags for the operation */struct msgbuf *msgp; /* pointer to the message buffer */int msgsz; /* message size */long msgtyp; /* desired message type */int msqid /* message queue ID to be used */...msgp = (struct msgbuf *)malloc((unsigned)(sizeof(struct msgbuf)- sizeof msgp->mtext + maxmsgsz));if (msgp == NULL) {(void) fprintf(stderr, "msgop: %s %d byte messages.\n","could not allocate message buffer for", maxmsgsz);exit(1);...msgsz = ...msgflg = ...if (msgsnd(msqid, msgp, msgsz, msgflg) == -1)perror("msgop: msgsnd failed");...msgsz = ...msgtyp = first_on_queue;msgflg = ...if (rtrn = msgrcv(msqid, msgp, msgsz, msgtyp, msgflg) == -1)perror("msgop: msgrcv failed");...
The full code listing for message_send.c's companion process, message_rec.c is as follows:
#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>#include <stdio.h>#define MSGSZ 128/* * Declare the message structure. */typedef struct msgbuf { long mtype; char mtext[MSGSZ];} message_buf;main(){ int msqid; key_t key; message_buf rbuf; /* * Get the message queue id for the * "name" 1234, which was created by * the server. */ key = 1234; if ((msqid = msgget(key, 0666)) < 0) { perror("msgget"); exit(1); } /* * Receive an answer of message type 1. */ if (msgrcv(msqid, &rbuf, MSGSZ, 1, 0) < 0) { perror("msgrcv"); exit(1); } /* * Print the answer. */ printf("%s\n", rbuf.mtext); exit(0);}
The essential points to note here are:
The Message queue is opened with msgget (message flag 0666) and the samekey as message_send.c.
A message of the same type 1 is received from the queue with the message ``Did you get this?'' stored in rbuf.mtext.
The following suite of programs can be used to investigate interactively a variety of massage passing ideas (see exercises below).
The message queue must be initialised with the msgget.c program. The effects of controlling the queue and sending and receiving messages can be investigated with msgctl.c and msgop.c respectively.
/* * msgctl.c: Illustrate the msgctl() function. * * This is a simple exerciser of the msgctl() function. It allows * you to perform one control operation on one message queue. It * gives up immediately if any control operation fails, so becareful * not to set permissions to preclude read permission; you won'tbe * able to reset the permissions with this code if you do. */#include <stdio.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>#include <time.h>static void do_msgctl();extern void exit();extern void perror();static char warning_message[] = "If you remove read permissionfor \ yourself, this program will fail frequently!";main(){ struct msqid_ds buf; /* queue descriptor buffer for IPC_STAT and IP_SET commands */ int cmd, /* command to be given to msgctl() */ msqid; /* queue ID to be given to msgctl() */ (void fprintf(stderr, "All numeric input is expected to follow C conventions:\n"); (void) fprintf(stderr, "\t0x... is interpreted as hexadecimal,\n"); (void) fprintf(stderr, "\t0... is interpreted as octal,\n"); (void) fprintf(stderr, "\totherwise, decimal.\n"); /* Get the msqid and cmd arguments for the msgctl() call. */ (void) fprintf(stderr, "Please enter arguments for msgctls() as requested."); (void) fprintf(stderr, "\nEnter the msqid: "); (void) scanf("%i", &msqid); (void) fprintf(stderr, "\tIPC_RMID = %d\n", IPC_RMID); (void) fprintf(stderr, "\tIPC_SET = %d\n", IPC_SET); (void) fprintf(stderr, "\tIPC_STAT = %d\n", IPC_STAT); (void) fprintf(stderr, "\nEnter the value for the command: "); (void) scanf("%i", &cmd); switch (cmd) { case IPC_SET: /* Modify settings in the message queue control structure.*/ (void) fprintf(stderr, "Before IPC_SET, get currentvalues:"); /* fall through to IPC_STAT processing */ case IPC_STAT: /* Get a copy of the current message queue control * structure and show it to the user. */ do_msgctl(msqid, IPC_STAT, &buf); (void) fprintf(stderr, ] "msg_perm.uid = %d\n", buf.msg_perm.uid); (void) fprintf(stderr, "msg_perm.gid = %d\n", buf.msg_perm.gid); (void) fprintf(stderr, "msg_perm.cuid = %d\n", buf.msg_perm.cuid); (void) fprintf(stderr, "msg_perm.cgid = %d\n", buf.msg_perm.cgid); (void) fprintf(stderr, "msg_perm.mode = %#o, ", buf.msg_perm.mode); (void) fprintf(stderr, "access permissions = %#o\n", buf.msg_perm.mode & 0777); (void) fprintf(stderr, "msg_cbytes = %d\n", buf.msg_cbytes); (void) fprintf(stderr, "msg_qbytes = %d\n", buf.msg_qbytes); (void) fprintf(stderr, "msg_qnum = %d\n", buf.msg_qnum); (void) fprintf(stderr, "msg_lspid = %d\n", buf.msg_lspid); (void) fprintf(stderr, "msg_lrpid = %d\n", buf.msg_lrpid); (void) fprintf(stderr, "msg_stime = %s", buf.msg_stime ? ctime(&buf.msg_stime) : "Not Set\n"); (void) fprintf(stderr, "msg_rtime = %s", buf.msg_rtime ? ctime(&buf.msg_rtime) : "Not Set\n"); (void) fprintf(stderr, "msg_ctime = %s", ctime(&buf.msg_ctime)); if (cmd == IPC_STAT) break; /* Now continue with IPC_SET. */ (void) fprintf(stderr, "Enter msg_perm.uid: "); (void) scanf ("%hi", &buf.msg_perm.uid); (void) fprintf(stderr, "Enter msg_perm.gid: "); (void) scanf("%hi", &buf.msg_perm.gid); (void) fprintf(stderr, "%s\n", warning_message); (void) fprintf(stderr, "Enter msg_perm.mode: "); (void) scanf("%hi", &buf.msg_perm.mode); (void) fprintf(stderr, "Enter msg_qbytes: "); (void) scanf("%hi", &buf.msg_qbytes); do_msgctl(msqid, IPC_SET, &buf); break; case IPC_RMID: default: /* Remove the message queue or try an unknown command. */ do_msgctl(msqid, cmd, (struct msqid_ds *)NULL); break; } exit(0);}/* * Print indication of arguments being passed to msgctl(), call * msgctl(), and report the results. If msgctl() fails, do not * return; this example doesn't deal with errors, it just reports * them. */static voiddo_msgctl(msqid, cmd, buf)struct msqid_ds *buf; /* pointer to queue descriptor buffer */int cmd, /* command code */ msqid; /* queue ID */{ register int rtrn; /* hold area for return value from msgctl()*/ (void) fprintf(stderr, "\nmsgctl: Calling msgctl(%d, %d,%s)\n", msqid, cmd, buf ? "&buf" : "(struct msqid_ds *)NULL"); rtrn = msgctl(msqid, cmd, buf); if (rtrn == -1) { perror("msgctl: msgctl failed"); exit(1); } else { (void) fprintf(stderr, "msgctl: msgctl returned %d\n", rtrn); }}
/* * msgop.c: Illustrate the msgsnd() and msgrcv() functions. * * This is a simple exerciser of the message send and receive * routines. It allows the user to attempt to send and receive asmany * messages as wanted to or from one message queue. */#include <stdio.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>static int ask();extern void exit();extern char *malloc();extern void perror();char first_on_queue[] = "-> first message on queue", full_buf[] = "Message buffer overflow. Extra message text\ discarded.";main(){ register int c; /* message text input */ int choice; /* user's selected operation code */ register int i; /* loop control for mtext */ int msgflg; /* message flags for the operation */ struct msgbuf *msgp; /* pointer to the message buffer */ int msgsz; /* message size */ long msgtyp; /* desired message type */ int msqid, /* message queue ID to be used */ maxmsgsz, /* size of allocated message buffer */ rtrn; /* return value from msgrcv or msgsnd */ (void) fprintf(stderr, "All numeric input is expected to follow C conventions:\n"); (void) fprintf(stderr, "\t0x... is interpreted as hexadecimal,\n"); (void) fprintf(stderr, "\t0... is interpreted as octal,\n"); (void) fprintf(stderr, "\totherwise, decimal.\n"); /* Get the message queue ID and set up the message buffer. */ (void) fprintf(stderr, "Enter msqid: "); (void) scanf("%i", &msqid); /* * Note that <sys/msg.h> includes a definition of structmsgbuf * with the mtext field defined as: * char mtext[1]; * therefore, this definition is only a template, not astructure * definition that you can use directly, unless you want onlyto * send and receive messages of 0 or 1 byte. To handle this, * malloc an area big enough to contain the template - the size * of the mtext template field + the size of the mtext field * wanted. Then you can use the pointer returned by malloc as a * struct msgbuf with an mtext field of the size you want. Note * also that sizeof msgp->mtext is valid even though msgpisn't * pointing to anything yet. Sizeof doesn't dereference msgp,but * uses its type to figure out what you are asking about. */ (void) fprintf(stderr, "Enter the message buffer size you want:"); (void) scanf("%i", &maxmsgsz); if (maxmsgsz < 0) { (void) fprintf(stderr, "msgop: %s\n", "The message buffer size must be >= 0."); exit(1); } msgp = (struct msgbuf *)malloc((unsigned)(sizeof(structmsgbuf) - sizeof msgp->mtext + maxmsgsz)); if (msgp == NULL) { (void) fprintf(stderr, "msgop: %s %d byte messages.\n", "could not allocate message buffer for", maxmsgsz); exit(1); } /* Loop through message operations until the user is ready to quit. */ while (choice = ask()) { switch (choice) { case 1: /* msgsnd() requested: Get the arguments, make the call, and report the results. */ (void) fprintf(stderr, "Valid msgsnd message %s\n", "types are positive integers."); (void) fprintf(stderr, "Enter msgp->mtype: "); (void) scanf("%li", &msgp->mtype); if (maxmsgsz) { /* Since you've been using scanf, you need the loop below to throw away the rest of the input on the line after the entered mtype before you start reading the mtext. */ while ((c = getchar()) != '\n' && c != EOF); (void) fprintf(stderr, "Enter a %s:\n", "one line message"); for (i = 0; ((c = getchar()) != '\n'); i++) { if (i >= maxmsgsz) { (void) fprintf(stderr, "\n%s\n", full_buf); while ((c = getchar()) != '\n'); break; } msgp->mtext[i] = c; } msgsz = i; } else msgsz = 0; (void) fprintf(stderr,"\nMeaningful msgsnd flag is:\n"); (void) fprintf(stderr, "\tIPC_NOWAIT =\t%#8.8o\n", IPC_NOWAIT); (void) fprintf(stderr, "Enter msgflg: "); (void) scanf("%i", &msgflg); (void) fprintf(stderr, "%s(%d, msgp, %d, %#o)\n", "msgop: Calling msgsnd", msqid, msgsz, msgflg); (void) fprintf(stderr, "msgp->mtype = %ld\n", msgp->mtype); (void) fprintf(stderr, "msgp->mtext = \""); for (i = 0; i < msgsz; i++) (void) fputc(msgp->mtext[i], stderr); (void) fprintf(stderr, "\"\n"); rtrn = msgsnd(msqid, msgp, msgsz, msgflg); if (rtrn == -1) perror("msgop: msgsnd failed"); else (void) fprintf(stderr, "msgop: msgsnd returned %d\n", rtrn); break; case 2: /* msgrcv() requested: Get the arguments, make the call, and report the results. */ for (msgsz = -1; msgsz < 0 || msgsz > maxmsgsz; (void) scanf("%i", &msgsz)) (void) fprintf(stderr, "%s (0 <= msgsz <= %d): ", "Enter msgsz", maxmsgsz); (void) fprintf(stderr, "msgtyp meanings:\n"); (void) fprintf(stderr, "\t 0 %s\n", first_on_queue); (void) fprintf(stderr, "\t>0 %s of given type\n", first_on_queue); (void) fprintf(stderr, "\t<0 %s with type <= |msgtyp|\n", first_on_queue); (void) fprintf(stderr, "Enter msgtyp: "); (void) scanf("%li", &msgtyp); (void) fprintf(stderr, "Meaningful msgrcv flags are:\n"); (void) fprintf(stderr, "\tMSG_NOERROR =\t%#8.8o\n", MSG_NOERROR); (void) fprintf(stderr, "\tIPC_NOWAIT =\t%#8.8o\n", IPC_NOWAIT); (void) fprintf(stderr, "Enter msgflg: "); (void) scanf("%i", &msgflg); (void) fprintf(stderr, "%s(%d, msgp, %d, %ld, %#o);\n", "msgop: Calling msgrcv", msqid, msgsz, msgtyp, msgflg); rtrn = msgrcv(msqid, msgp, msgsz, msgtyp, msgflg); if (rtrn == -1) perror("msgop: msgrcv failed"); else { (void) fprintf(stderr, "msgop: %s %d\n", "msgrcv returned", rtrn); (void) fprintf(stderr, "msgp->mtype = %ld\n", msgp->mtype); (void) fprintf(stderr, "msgp->mtext is: \""); for (i = 0; i < rtrn; i++) (void) fputc(msgp->mtext[i], stderr); (void) fprintf(stderr, "\"\n"); } break; default: (void) fprintf(stderr, "msgop: operation unknown\n"); break; } } exit(0);}/* * Ask the user what to do next. Return the user's choice code. * Don't return until the user selects a valid choice. */staticask(){ int response; /* User's response. */ do { (void) fprintf(stderr, "Your options are:\n"); (void) fprintf(stderr, "\tExit =\t0 or Control-D\n"); (void) fprintf(stderr, "\tmsgsnd =\t1\n"); (void) fprintf(stderr, "\tmsgrcv =\t2\n"); (void) fprintf(stderr, "Enter your choice: "); /* Preset response so "^D" will be interpreted as exit. */ response = 0; (void) scanf("%i", &response); } while (response < 0 || response > 2); return(response);}
Write a 2 programs that will both send and messages and construct the following dialog between them
(Process 1) Sends the message "Are you hearing me?"
(Process 2) Receives the message and replies "Loud and Clear".
(Process 1) Receives the reply and then says "I can hear you too".
Exercise 12756
Compile the programs msgget.c, msgctl.c and msgop.c and then
investigate and understand fully the operations of the flags (access, creation etc. permissions) you can set interactively in the programs.
Use the programs to:
Send and receive messages of two different message types.
Place several messages on the queue and inquire about the state of the queue with msgctl.c. Add/delete a few messages (using msgop.c and perform the inquiry once more.
Use msgctl.c to alter a message on the queue.
Use msgctl.c to delete a message from the queue.
Exercise 12757
Write a server program and two client programs so that the server can communicate privately to each client individually via a single message queue.
Exercise 12758
Implement a blocked or synchronous method of message passing using signal interrupts.
여기는 가산디지털단지 W몰에 있는 7그램이라는 카페다. 무선 인터넷도 되니 시간때우기엔 딱인데... 오늘은 왠 목소리 큰 커플이 엄청 떠들어 대고 있는중...ㅜㅜ 웃는 소리가 어찌나 큰지...
프로젝트가 마무리 되고 조금은 여유있는 나날들을 보내고 있지만 심신이 피곤한 이유는 뭘까. 뭔가 많이 부족하다. 일도 손에 잘 잡히지 않고... 여유있을때 뭔가 해야지라는 강박관념 때문일까? 맘은 편하게 먹으려 해도 쉽지가 않다. 조금씩 조금씩 차분한 마음으로 돌아가려고 노력해야지...
HTTP server push (also known as HTTP streaming) is a mechanism for sending data from a web server to a web browser. HTTP server push can be achieved through several mechanisms.
Generally the web server does not terminate a connection after
response data has been served to a client. The web server leaves the
connection open such that if an event is received, it can immediately
be sent to one or multiple clients. Otherwise the data would have to be
queued until the client's next request is received. Most web servers
offer this functionality via CGI (e.g. NPH scripts on Apache).
Another mechanism is related to a special MIME type called multipart/x-mixed-replace, which was introduced by Netscape
in 1995. Web browsers would interpret this as a document changing
whenever the server felt like pushing a new version to the client.[1][2] It is still supported by Firefox, Opera and Safari today, but traditionally ignored by Microsoft.[3] It can be applied to HTML documents, but also for streaming images in webcam applications.
The WHATWG Web Applications 1.0 proposal[4]
included a mechanism to push content to the client. On September 1,
2006, the Opera web browser implemented this new experimental
technology in a feature called "Server-Sent Events."[5][6] It is now being standardized as part of HTML5.[7]
Another related part of HTML5 is the Web Sockets API, which allows a
web server and client to communicate over a full-duplex TCP connection.[8]Web Sockets are available on Google Chrome since 4.0.249.0[9], and there is a JavaScript library by Kaazing that emulates them
RTSP protocol is the default protocol for
streaming Windows Media. RTSP protocol is also used for streaming
RealMedia/RealVideo/RealAudio, streaming QuickTime video (.mov, .mp4,
.sdp streams).
MMS protocol is used for streaming Windows Media only.
RTSP using UDP is called RTSPU
RTSP using TCP is called RTSPT
MMS using UDP is called MMSU
MMS using TCP is called MMST
PNM protocol is used for RealMedia/RealVideo/RealAudio streaming only. RTMP protocol is used for Flash audio and video streams only.
Media files can also be streamed through HTTP or other protocols.
The majority of streams are streamed through HTTP, RTSP, MMS
and RTMP. PNM protocol is usually not used on the newest servers, but
such streams are not very rare.
HTTP Streaming
HTTP streaming is a mechanism for sending data from a
Web server to a Web browser in response to an event. HTTP Streaming is
achieved through several common mechanisms.
In one such mechanism the web server does not terminate the
response to the client after data has been served. This differs from
the typical HTTP cycle in which the response is closed immediately
following data transmission.
The web server leaves the response open such that if an event
is received, it can immediately be sent to the client. Otherwise the
data would have to be queued until the client's next request is made to
the web server. The act of repeatedly queing and re-requesting
information is known as a Polling mechanism.
Typical uses for HTTP Streaming include market data
distribution (stock tickers), live chat/messaging systems, online
betting and gaming, sport results, monitoring consoles and Sensor
network monitoring.
HTTP protocol usually uses port 80 or 8080.
MMS - Microsoft Media Services
Microsoft's streaming server uses the Microsoft Media
Services (MMS) protocol (also called NetShow Services) to transfer
unicast data. MMS can be transported via UDP or TCP (MMSU and MMST
protocols). If the Windows Media Player client cannot negotiate a good
connection using MMS over UDP, it will resort to MMS over TCP. If that
fails, the connection can be made using a modified version of HTTP
(always over TCP). This is not as ideal for streaming as MMS over UDP,
but ensures connectivity nonetheless.
The default protocol for streaming Windows Media is not MMS, but RTSP.
The default port for MMS is 1755.
RTSP - Real Time Streaming Protocol
The Real Time Streaming Protocol (RTSP), developed by
the IETF and published in 1998 as RFC 2326, is a protocol for use in
streaming media systems which allows a client to remotely control a
streaming media server, issuing VCR-like commands such as "play" and
"pause", and allowing time-based access to files on a server.
Some RTSP servers use RTP as the transport protocol for the
actual audio/video data. Many RTSP servers use RealNetworks's
proprietary RDT as the transport protocol.
RTSP can be transported via UDP or TCP (RTSPU and RTSPT protocols).
The default port for RTSP is 554.
PNM/PNA
The first version of RealAudio used a proprietary
protocol called PNA or PNM to send streaming audio data. RealNetworks
later switched to the IETF standardized Real Time Streaming Protocol
(RTSP), but they use RTSP only to manage the connection.
The default port for PNM is 7070.
RTMP - Real Time Messaging Protocol
Real Time Messaging Protocol (RTMP) Is a proprietary
protocol developed by Adobe Systems (formerly developed by Macromedia)
that is primarily used with Macromedia Flash Media Server to stream
audio and video over the internet to the Adobe Flash Player client.
1. 비난·비판·불평 금지
입술의 30초가 가슴에서는 30년을 갑니다. ‘비난, 비판, 불평하지 마라’는 카네기 인간관계의 첫번째 원칙이자 유일한 부정적인 표현입니다. 굳이 ‘하라’가 아닌 ‘하지 마라’라는 금기어를 사용한 이유는 백해무익하기 때문이죠. 잘못을 저지른 사람들조차 스스로 자신의 잘못을 인정하는 사람은 거의 없습니다. 위험한 비난, 비판, 불평을 하지 마세요. 왜냐하면 그것은 인간의 소중한 자존심에 상처를 주고, 그 상처는 때로는 원한을 불러일으키기 때문입니다. 비난은 상대방의 가슴에 비수를 꽂는 것과 같습니다.
2. 솔직하고 진지하게 칭찬하라
칭찬의 핵심은 바로 솔직함과 진지함에 있습니다. 우리 삶에 있어서 가장 간과되기 쉬운 덕목이 있다면 그것은 칭찬과 감사입니다. 음식을 먹을 때 주인에게 최고의 요리였다고 칭찬해 보세요. 동료가 당신에게 친절을 베풀었을 때, 프로젝트를 성공적으로 마쳤을 때, 팀을 위해 편의를 제공했을 때, 그것을 진지하게 인정해 주세요. “정말 잘했어, 역시 너밖에 없어, 난 널 믿어.” 사람들은 그런 칭찬과 감사, 인정의 말들을 아마도 소중한 보석처럼 가슴 깊이 오래도록 간직할 겁니다. 당신이 이미 잊어버리더라도 말이죠. 장미꽃을 전해준 사람의 손에는 장미향이 남아있는 법입니다.
3. 사람들의 열렬한 욕구를 불러일으켜라
사람들의 열렬한 욕구를 불러일으키려면 그 사람이 원하는 것을 알아야 합니다. 사람들은 자신들이 원하는 것에만 관심이 있기 때문이죠. 만약 세일즈맨이 자신이 제공하는 서비스가 우리의 문제 해결에 도움이 된다는 것을 보여 준다면, 우리는 그 제품을 구입할 것입니다. 내가 원하는 것이 아니라 상대방이 원하는 것이 무엇인가? 우리 가족이 원하는 것이 무엇인가? 그들이 갖고자 하는 것이 무엇인가? 그들이 성취하는 데 있어 무엇을 도와줄까? 이것을 생각하면 다른 사람들의 마음에 열렬한 욕구를 불러일으킬 수 있습니다. 링컨은 “어떤 사람을 내 사람으로 만들려면, 먼저 당신이 그의 진정한 친구임을 확신시켜야 한다”고 말했습니다.
4. 다른 사람에게 순수한 관심을 기울여라
비난보다 더 무서운 것은 무관심입니다. 어떤 사람과도 좋은 관계를 유지하려면 상대방에게 순수한 마음을 갖고 있다는 것을 느끼게 하면 됩니다. 순수한 관심의 핵심은 사랑하는 마음입니다. 서로가 미처 알지 못했던 공통 관심사를 발견하고 놀라게 된 경험은 누구나 있을 것입니다. 누군가에게 진지하고 순수한 관심을 기울이면, 다른 사람으로부터 관심과 시간 또한 협력까지 얻어낼 수 있습니다. 내가 먼저 다가가 인사를 하고 악수를 청해 보세요.
5. 미소를 지어라
미소는 인간이 표현할 수 있는 가장 아름다운 예술입니다. 미소는 꽃이 피는 것과 같습니다. 사람의 ‘얼굴’에서 ‘얼’이란 정신, 사고, 사상, 이념을 나타내고, ‘굴’은 보인다는 의미입니다. 얼굴을 보면 그 사람에 대해 알 수 있습니다.
도전적인 상황 속에서 미소가 만들어 내는 결과는 매우 놀랍습니다. 눈살을 찌푸리고 있는 사람들이나 고개를 돌리고 외면하려는 사람들에게 당신의 미소는 구름을 뚫고 나오는 햇빛과도 같습니다.
6. 당사자에게는 이름이 그 어떤 것보다도 기분 좋고 중요한 말이다.
사람의 신체 모두가 중요하겠지만 이름은 특히 그 사람을 상징합니다. 이름은 개인을 타인과 구분해줄 뿐 아니라 그 사람을 독특하고 중요한 존재로 만들어 줍니다.
사람들의 이름을 꼭 기억해서 불러 주세요. 그리고 이름을 부를 때 작은 칭찬도 곁들여 보세요. 그렇게 함으로써 상대방에게 특별한 감정을 심어줄 수 있답니다. 만약 사람들의 이름이나 철자를 실수하게 된다면 예기치 않은 손해를 보게 될 것입니다. 이름을 잘 기억하려면 먼저 상대방의 인상과 함께 명확하게 들으세요. 그리고 나서 마음속으로 여러 번 반복하고, 대화 도중 자주 사용해 보세요.
7. 경청하라
경청은 바로 친구를 만들고, 경청을 통한 아이디어는 돈을 벌게 해 줍니다. 다른 사람의 말에 귀 기울이면 다른 사람에 대해 알 수 있고, 상대방과 우호적인 관계를 맺을 수 있습니다. 하지만 대화 중에 조용히 듣고만 있는 것으로 충분하지는 않습니다. 적절한 질문을 할 줄 알아야 합니다. 피터 드러커는 모든 경영관리 문제의 60% 이상은 잘못된 커뮤니케이션에서 기인한다고 말합니다. 많은 사람들이 다른 사람에게 좋은 인상을 심어 주는 데 실패하곤 하는데, 그 이유는 귀를 열어 상대방의 말을 경청하기보다는 ‘저 사람 말이 끝나면, 나는 무슨 말을 할까?’에 더 큰 관심이 있기 때문입니다. 가족이나 직원의 말에 공감하면서 잘 경청해 보세요.
8. 상대방의 관심사에 대해 이야기하라
영업을 하려고 하지 말고 고객의 관심사가 무엇인지 알고 좋은 것을 소개해 주려는 마음으로 비즈니스를 하면 잘 할 수 있습니다. 흥미로운 사람이 되고 싶나요? 그렇다면 나 자신에 대한 관심의 채널을 잠시 끄고, 다른 사람의 관심사에 채널을 맞춰 보세요. 위대한 리더들은 음악을 좋아하는 사람에게는 음악에 대해서, 스포츠를 좋아하는 사람에게는 스포츠에 대해서 대화를 나눕니다. 사람들은 자신이 가장 소중히 여기는 보물에 대해서 이야기하고 싶어합니다.
9. 상대방으로 하여금 중요하다는 느낌이 들게 하라
‘ 당신이 대접받고자 하는 대로 다른 사람을 대접하라.’ 성서에 나오는 이 황금률에 따라 행동합시다. 사람들이 당신을 좋아하게 만드는 방법을 알고 있나요? 상대방으로 하여금 중요한 존재라는 느낌을 갖게 해주면, 즉시 상대방과 긍정적인 관계를 만들어 갈 수 있습니다. 누구나 자신의 가치를 인정받기를 원하고 이 세상 속에서 꼭 필요한 사람이기를 원합니다. 만약 공공장소나 은행에서 긴 줄을 서서 순서를 기다려야 하는 일이 생긴다면, 분주하게 일하고 있는 카운터 직원에게 ‘훌륭한 점’을 찾아서 이야기해 주세요. 당신은 그를 행복하게 만들어 줄 것입니다. 그리고 당신도 행복해질 것입니다.
10. 최선의 논쟁은 피하는 것이다
논쟁에서 이겨도 감정을 얻어내지 못하면 결코 승리자가 될 수 없습니다. 누구도 논쟁에서 결코 승리할 수 없습니다. 논쟁에서 진다면 진 상태로 끝나는 것이고, 이긴다고 해도 그것은 결국 지는 것입니다. 논쟁은 상대방에게 열등감을 주고, 자존심에 상처를 주기 때문이지요. 논리적인 사람은 거의 없습니다. 대부분의 사람들은 편견을 갖고 있거나 생각이 한쪽으로 치우쳐 있어 선입관·질투·의심 등으로 인해 판단이 흐려지기 때문에 자신이 갖고 있는 생각을 쉽게 바꾸려 하지 않습니다. 당신은 어느 편을 택하는 것이 좋다고 생각하십니까? 자기 의사와는 반대로 설득당한 사람은 그래도 자신의 의견을 굳게 지킵니다.
11. 결코 당신이 틀렸다고 말하지 마라
‘ 상대방을 이해하는 것은 꽃이 태양을 필요로 하는 것과 같습니다.’ 만약 어떤 사람이 의견 발표를 했는데, 당신이 생각하기에 그 사람이 확실히 틀렸다면, 다음과 같이 이야기를 해보세요. “선생님의 의견을 다른 방법으로 생각해 보면 어떨까요? 물론 제가 틀렸을지도 모릅니다. 저는 종종 그렇지요. 제가 말씀드리는 내용을 함께 검토해 보시겠습니까?” 만약 당신이 상대방에게 “넌 틀렸어!”라고 말한다고 해서, 그 사람이 당신의 의견에 동의하는 것은 아닙니다. 이 말은 상대방의 자부심·지성·판단력·자존심 등에 바로 타격을 주게 됩니다. 그것은 상대방으로 하여금 바로 보복해 주고 싶은 마음을 솟아나게 하지요.
12. 잘못을 했다면 즉시 인정하라
100 명의 중의 1명만이 자신의 잘못을 인정하는 용기를 발휘합니다. 당신이 잘못을 했으면 자신의 잘못을 인정하는 용기를 가지세요. 급하게 운전하다가 속도위반이 되었다면 경찰관에게 솔직히 자신의 잘못을 인정해 보세요. 이것은 잘못이나 실수를 명확하게 해줄 뿐 아니라, 그에 따른 문제를 해결하는 데도 도움이 됩니다. 어리석은 사람은 자신의 실수를 변명하고, 방어 자세를 취하곤 합니다. 사실 대부분의 사람들이 그렇게 하지요. 하지만 자신의 잘못을 인정하는 용기를 가진 사람은 보통의 사람들이 느낄 수 없는 환희를 경험할 수 있습니다.
13. 우호적인 태도로 말을 시작하라
당신이 만약 어떤 회사의 제품을 사용하는데, 고객 서비스가 엉망이었다면 어떻게 하시겠습니까? 당장 소리를 치는 대신 먼저 우호적인 대화를 통해 시작하세요. 혹시 팀 내에 문제가 있으신가요? 그래서 마음이 흥분되어 있는 상태인가요? 크게 심호흡을 하면서 마음을 안정시켜 보세요. 오늘 할 말이 있으면 내일 하시고, 내일 당장 호통 칠 일이 있다면 하루가 지난 다음에 우호적인 태도로 시작해 보세요. 마음을 보다 쉽게 변화시킬 수 있습니다. 세상에서 가장 먼 거리는 흥미롭게도 머리에서 발까지랍니다. 인간관계의 원칙을 지키기 위한 가장 중요한 것은 ‘실천을 하느냐, 머리로만 알고 있느냐’ 하는 것입니다.
14. 상대방이 당신의 말에 즉시 ‘Yes’라고 대답하게 하라
혹시 업무상 어려운 상대방을 만나셨나요. 그렇다면 먼저 그 사람이 확실히 ‘예’라고 대답할 만한 질문을 만듭니다. 계속해서 ‘예’라는 답변을 받아낼 수 있다면, 당신은 몇 분 전에 그 사람이 강력하게 부인하던 문제에 대해서도 ‘예’라는 대답을 얻어낼 수 있을 것입니다. 사람들과 대화를 나눌 때, 서로 다른 점에 대해서 대화를 시작하지 마세요. 서로 공유할 수 있는 주제, 서로 동의하는 주제에 대해서 대화를 시작해 보세요. 긍정적으로 시작하는 말과 행동은 상대방의 마음을 열게 하며 대화를 부드럽게 해준답니다.
15. 상대방이 많은 이야기를 하게 하라
당신은 자신의 성과를 주로 동료에게 이야기하는 편인가요? 진정으로 상대방의 협조를 구하고 싶다면 그로 하여금 많은 이야기를 하도록 도와 주세요. 사람들은 자신이 이야기하고 싶은 주제가 있으면 다른 사람의 이야기에는 주의를 기울이지 않는답니다. 먼저 상대방이 하고 싶은 이야기를 열린 마음으로 인내심을 가지고 경청하세요. 주의 깊게 경청하는 사람이 적절한 질문을 잘 할 수 있고, 상대방으로 하여금 많은 이야기를 할 수 있게 만들 수 있답니다. 당신이 진정한 친구를 얻고자 한다면 그가 당신을 이기도록 해주십시오.
16. 상대방 아이디어인 듯이 느끼게 하라
어느 누구도 자신이 누군가에 의해 조종당하는 것을 좋아하지 않습니다. 오히려 자신의 주도적인 의사결정에 의해 움직이는 것을 좋아하죠. 상대방이 스스로 아이디어를 생각해낸 것처럼 느끼게 해주십시오. 당신이 스스로 발견한 아이디어에 대한 확신이 부족하다면, 그 아이디어를 상대방에게 제안하고 그 사람이 스스로 결론을 내리도록 하는 것이 좋습니다. 아주 자연스럽게 당신의 아이디어를 던져 주세요. 상대방이 그 아이디어를 곰곰이 생각해서 일치점을 찾아 행동하도록 말입니다.
17. 상대방의 관점에서 사물을 보라
매월 17일에는 망원경을 하나 준비하세요. 하늘의 아름다운 별을 바라보듯 상대방을 바라보고 그들의 관점에서 사물을 보도록 하세요. 상대방에게 “우리 회사 제품을 구입하세요”, “자선 단체에 기부금을 내주세요”라고 요청하기 전에 잠시 눈을 감고 상대방의 입장에서 생각해 보세요. 상대방의 관점에서 사물을 보는 태도는 상대방으로 하여금 당신과 협력하고자 하는 마음을 불러일으킬 것입니다. 강압적인 명령 대신 상대방의 관점에서 상황을 고려해 보세요. 그렇게 하면 예기치 못한 결과를 나타날 것입니다. 인간관계에 있어 성공을 원한다면 상대방의 입장에서 이해하려는 노력이 필요합니다.
18. 상대방의 생각·욕구에 공감하라
서로간의 논쟁을 멈추고 나쁜 감정을 없애 주면서 상대방에게 호감을 갖게 하여 당신의 말에 귀 기울이게 하는 마술적인 언어가 필요하다면 다음과 같은 말을 한번 해보세요. “당신이 그렇게 생각하는 것은 당연한 일입니다. 내가 당신이었더라도 그렇게 생각했을 것입니다.” 인간은 누구나 동정심을 갈망합니다. 열린 마음과 열린 태도는 상대방을 이해하고 공감하는 사람으로 만들 것입니다. 우호적인 감정을 갖게 하는 마술 주문을 외워 보세요. 사용할 마술 주문은 상대방의 생각이나 욕구에 공감해 주는 것입니다. 당신은 분명 사랑받게 될 것입니다.
19. 보다 고매한 동기에 호소하라
사람들이 행동을 하는 데는 두 가지 이유가 있습니다. 좋은 일이라는 생각이 들 때와 해야 할 필요가 있을 때입니다. 사람들은 누구나 존경받길 원하고, 좋은 사람, 이타적인 사람으로 평가받기를 원합니다. 사람들을 변화시키기 위해서는 보다 고매한 동기, 아름다운 마음에 호소해야 합니다. 사람들에게 인내, 공평, 정직 등과 같은 동기를 가지고 호소하세요. 인간은 정직하고자 하는 자신의 의무를 이행하기를 원하는 본성을 가지고 있습니다.
20. 당신의 생각을 극적으로 표현하라
현대는 드라마의 시대입니다. 사건 그 자체는 그다지 큰 힘을 발휘하지 못합니다. 사건이 흥미롭거나 활력 있고 드라마틱하게 연출되는 것이 중요한 시대입니다. 오늘이 당신 가족의 생일인가요? 그렇다면 아름다운 장미와 함께 아름다운 사연이 담긴 감사의 편지를 함께 전해 주세요. 그것을 받는 당사자는 이 세상에서 가장 행복한 표정을 짓게 될 것입니다. 그 모습을 보는 당신의 얼굴을 상상해 보셨나요? 당신의 상사, 고객, 친구들에게 아이디어를 제안할 기회가 있다면, 극적인 방법을 통해 쇼맨십을 발휘해 보세요. 리더는 마치 영화 속의 주인공처럼, 텔레비전 드라마의 연기자처럼 쇼맨십을 발휘해야 합니다. 가족들과 한번도 가보지 않은 장소에 가보거나, 먹어보지 않은 음식 또는 새로운 취미를 즐겨 보세요. 생활 그 자체가 이벤트가 될 수 있다면 행복은 언제나 우리 곁에 있을 것입니다.
21. 도전 의욕을 불러일으켜라
“ 역시 자네밖에 없어. 이번 일은 자네가 맡아주게. 자네라면 충분히 할 수 있을 거야. 난 잘 할 거라고 믿네.” 상대방의 협력을 얻기 원한다면, 사람들 내면 깊숙이 자리한 탁월해지고 싶은 욕구를 불러일으키세요. 높은 수준의 동기 부여된 팀원들을 얻길 원한다면 도전의욕을 불러일으키세요. 팀 목표 또는 개인목표에 대한 선의의 경쟁을 시작하는 것도 좋습니다. 열심히 일하는 사람은 많지만 자신의 일을 즐기는 사람은 그렇게 많지 않습니다. 매월 21일은 최후의 히든카드를 사용하는 날입니다. 이번주 중에 달성할 수 있는 주간 목표를 세워 보세요. 그리고 목표 리스트를 눈에 잘 보이는 곳에 붙여 두세요. ‘할 일’ 리스트도 좋고, ‘하지 말아야 할 일’ 리스트도 좋습니다. 주말에는 주간 목표 리스트를 보면서 달성 여부를 체크해 보세요. 작지만 스스로에게 도전장을 내미는 것입니다. 협력을 얻어내고 리더가 되기 위한 마지막 원칙, 비전과 열정을 갖고 도전의욕을 불러일으켜 보세요.
22. 시작은 칭찬과 감사의 말로
입으로는 칭찬의 말을! 손으로는 감사의 편지를! 발로는 어려운 이웃을 찾아가는 것! 이것이 진정한 사랑의 실천이요. 리더가 갖추어야 할 덕목이랍니다. 칭찬과 감사의 말을 한 후에 잘못을 지적하세요. 현명한 리더는 함께 일하는 팀원들에게 올바른 행동과 좋은 업무 습관이 필요한 상황이라면, 먼저 칭찬과 감사의 말로 시작합니다. 상처받은 감정은 보다 쉽게 누그러지고, 변화를 위한 노력들이 나타날 것입니다. 부득이 잘못을 지적해야 한다면 칭찬과 감사의 말로 시작해 보세요. 이 원칙은 연말 평가 때만 활용할 수 있는 것은 아닙니다. 한번 생각해 보세요. 과거의 당신에게도 매일매일의 일상 속에서 칭찬과 감사의 말이 필요했을 것입니다.
23. 잘못은 간접적으로 알게 하라
A : “000님! 지난주 보고서는 아주 훌륭했습니다. 그러나 보고서 중에 몇 개 잘못된 부분이 있었어요!”
B : “000님! 지난주 보고서는 아주 훌륭했습니다. 그리고 보고서 중 몇 가지가 교정되는 대로 이 훌륭한 보고서를 프레젠테이션하고 싶습니다. 기대하고 있겠습니다.”
A 대신 B 방법을 사용하면, 실패하지 않고 긍정적인 행동의 변화를 볼 수 있을 것입니다. 비평을 하면서도 미움을 사지 않으려면, 먼저 상대방의 말을 인정한 후에 그러나(but)를 그리고(and)로 바꿔 보세요. 누군가의 행동을 변화시키려면 잘못을 간접적으로 알게 해 보시기 바랍니다. 이것은 아주 놀라운 결과를 가져옵니다. 매일 ‘이해’라는 단어를 세 번 떠올리면서 ‘그러나’라는 단어를 당신의 단어사전에서 지워 버리세요! ‘그러나’를 ‘그리고’로 바꾸어 쓰기만 해도 사람들의 원망이나 미움을 받지 않고 그들의 잘못을 고칠 수가 있습니다. 상대방이 자신의 잘못을 간접적으로 알게 하십시오.
24. 상대방을 비평하기 전에 자신의 잘못을 인정하라
‘ 비록 실수를 계속하고 있는 중이라 하더라도, 자신의 실수를 인정하면 다른 사람의 행동을 바꿀 수 있다.’ 당신이 진정한 리더라면, 상대방을 비평하기 전에 자신의 잘못을 인정해 보세요. 만약 누군가가 “당신에게는 큰 잘못이 없습니다”라는 겸손한 태도로 이야기한다면 그 뒤 당신의 잘못을 지적받게 되더라도 그리 힘들지는 않을 것입니다. 겸손하게 자신의 잘못을 인정하고, 상대방을 존중하는 태도는 당신의 인간관계에 있어 기적적인 결과를 가져올 것입니다. 상대방의 신발을 신어 보세요. 상대방이 어린아이든 함께 일하는 동료든 이 원칙을 실천할 수 있는 가장 좋은 방법은 상대방의 입장이 되어 보는 것이지요. 그리고 당신의 과거를 찬찬히 설명해 주세요. 당신도 같은 실수를 했었고 어떻게 고치게 되었는지 말이에요.
25. 직접적으로 명령하지 말고 요청하라
사람들은 자신이 의사결정에 참여하게 될 때에 명령에 긍정적인 반응을 보입니다. 그러니 자발적으로 움직이게 하려면 명령하지 말고 요청해 보세요. 명령은 비록 불가피한 상황 속에서 내려진 것이라 할지라도, 분노하는 마음은 오래 지속될 것입니다. 직접적인 명령보다는 ‘물음표(?)’를 사용해서 요청해 보세요. 그러면 상대방은 스스로 잘못을 고치려고 할 것입니다. ‘당신은~해야 한다’로 표현하기보다는 ‘~하는 것이 어떨까요?’라는 말을 사용하시기 바랍니다. “좀더 다르게 처리할 수 있는 방법은 없을까요?” “이 업무를 좀더 효과적으로 해결할 방법을 생각해 보신 분은 안 계신가요?” “함께 협조하기 위해서 각자 시간이나 개인적 업무를 조정할 수 있는 방법이 없을까요?” “이것이 제대로 실행될 수 있을까요?” “이런 방법으로 한다면 괜찮겠습니까?”
26. 상대방의 체면을 세워 주어라
‘ 사람의 자존심(존엄성)에 상처를 주는 것은 죄악이다.’ 당신은 기분이 손상 당했을 때 기분이 어땠나요? 다른 사람의 감정을 사려 깊게 살펴보는 사람은 그리 많지 않습니다. 우리는 보통 타인의 실수를 찾아내서, 그 실수를 드러내고 비난하기를 좋아합니다. 상대방의 자존감에 상처를 준다는 사실은 외면한 채 말이죠. 잠시 멈춰 서서 생각해 보고, 좀더 사려 깊은 언어를 사용하면서 진심으로 상대방을 이해하는 태도를 가지세요. 그것은 상대방의 아픔을 가볍게 해줄 것입니다. 상대방이 불이익도 감수하게 하려면 상대방의 체면을 세워 주세요.
27. 아주 작은 진전에도 칭찬을 아끼지 마라
진전이 있을 때마다 칭찬을 하십시오. 동의는 진심으로, 칭찬은 아낌없이 하십시오. 칭찬은 인간의 영혼을 따뜻하게 해주는 햇볕과도 같습니다. 만일 당신이 상대방을 변화시키기 원한다면, 아주 작은 진전에도 칭찬을 아끼지 마세요. 이때의 칭찬은 마음에서 우러난 구체적이고 진심어린 것이어야 합니다. 이 원칙의 중심에는 사랑이 있어야 합니다. 사랑은 먹구름 속에 피어나는 무지개와 같습니다. 인간의 잠재력은 비난 속에서 시들고 격려 속에서 피어나는 꽃이랍니다. 사람을 성공시키고 사람의 마음을 사로잡는 방법은 비록 사소한 일이라도 아낌없이 칭찬을 해주는 것입니다.
28. 상대방이 훌륭한 명성을 갖도록 해 주어라
상대방에 대한 진심어린 기대는 사람의 마음을 사로잡을 수 있습니다. 상대방이 훌륭한 명성을 갖도록 해주세요. 귀여운 강아지를 키우고 있나요? 개에게도 좋은 이름을 지어 주어야 합니다. 그러면 그는 당신을 실망시키지 않기 위해 최선을 다할 것입니다. 그러나 상대방의 반감을 사지 않고 문제를 바르게 해결할 수 있는 방법은 상대방에게도 당신이 개발시켜 주고 싶은 장점이 있다고 가정하고, 그것에 대해 자주 말해 주는 것입니다.
29. 격려해 주어라
격려는 잘못은 쉽게 고칠 수 있다는 것을 느끼게 해줍니다. 다른 사람에게 잠재된 능력이 있다고 말하면, 그들은 자신의 우수성을 보여 주기 위해서 성공할 때까지 꾸준히 그 일을 해나갈 것입니다. 에머슨은 “가장 강하고 가장 뛰어난 사람만이 반드시 인생의 싸움에서 승리하는 것은 아니다. 최후의 승리를 거두는 자는 ‘나는 할 수 있다.’고 생각하는 사람이다”라고 말했습니다. 상대방의 실수를 강조함으로써 의욕을 꺾어 버려서는 안 되겠죠. 진정으로 다른 사람이 발전하도록 도와주길 원하시나요? 그렇다면 잘하는 것과 진전된 성과에 대해서 항상 칭찬해 주고 그의 가능성을 격려해 주세요.
30. 당신 제안을 상대방이 기꺼이 하도록 만들라
훌륭한 지도자는 사람의 행동이나 태도를 변화시킬 필요를 느꼈을 때, 자신에 대한 이익은 잊어버리고, 다른 사람에 대한 이익에 집중합니다. 당신이 제안하는 일을 함으로써 상대방에게 어떤 이익이 돌아가겠는가를 생각해 보세요. 그리고 그러한 이익을 상대방의 소망과 일치시키세요. 배우는 청중이 얻게 될 즐거움을 생각하면서 연기에 최선을 다 합니다. 여러분도 나의 이익보다는 상대방이 얻게 될 이익을 생각해 보세요. 상대방이 얻게 될 이익을 고려하고 그것을 알려 줌으로써, 상대방은 즐거운 마음으로 일하게 될 것입니다.