Linux ÇÁ·Î±×·¡¸Ó¶ó¸é socket, IO multiplexing, Asynchronous IO ¿¡ ´ëÇؼ´Â ¾î´ÀÁ¤µµ Àͼ÷Çϸ®¶ó »ý°¢ÇÏÁö¸¸, ÀÌ ±Û¿¡¼´Â ¼¹ö¸¦ óÀ½ ¸¸µé¾îº¸´Â »ç¶÷µé¿¡°Ôµµ µµ¿òÀÌ µÇµµ·Ï ÃÖ´ëÇÑÀÇ ¼³¸íÀ» ºÙ¿©°¡·Á°í °èȹÁßÀÌ´Ù. ¸¹Àº ¼º¿ø ºÎŹ
- 1 socket ÇÁ·Î±×·¡¹Ö ±âº»
- 1.1 socket()
- 1.2 bind()
- 1.3 listen()
- 1.4 read() ¿Í write()
1.1 socket() #
#include <sys/types.h>
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
socket() ÇÔ¼ö´Â, Åë½ÅÀ» À§ÇÑ ³¡Á¡ ÇÑ°³¸¦ ¸¸µç´Ù (¹«½¼ ¼Ò¸®³Ä! :@). ¿ö³« ¿©·¯°¡Áö Åë½Å¿¡ »ç¿ëÇÒ ¼ö ÀÖ´Â ÇÔ¼öÀÌÁö¸¸, ÀÌ ±Û¿¡¼´Â TCP/IP Åë½ÅÀ» À§ÇÑ ºÎºÐ¿¡ ±¹ÇÑÇؼ, ¹º°¡ Åë½ÅÀ» ÇϱâÀ§ÇÑ ¸Å°³Ã¼(ÀÌ°ÍÀ» fd, file descriptor ¶ó°í ÇÑ´Ù)¸¦ ÇÑ°³ »ý¼ºÇϴµ¥ ¾´´Ù.
int fd;
if ((fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
fprintf(stderr, "socket() error\n");
exit(-1);
}
socket() ÇÔ¼öÀÇ ÆĶó¹ÌÅÍ domain°ú typeÀº TCP/IPÀÇ IP¿Í TCP¸¦ ÀǹÌÇÑ´Ù. Âü°í·Î UDPÅë½ÅÀ» À§Çؼ´Â type¿¡ SOCK_DGRAM À» ¾´´Ù. ÇÁ·Î±×·¡¹Ö¿¡¼ StreamÀ̶ó´Â ´Ü¾î´Â ¿¬¼ÓÀûÀ¸·Î ÁÖ¸£¸¤ ºÙ¾îÀÖ´Â ÀڷᱸÁ¶¸¦ °¡¸®Å°´Âµ¥, Åë½ÅÀ» ÇÏ´Ùº¸¸é Ç×»ó ¸ÕÀúº¸³½ µ¥ÀÌÅÍ°¡ ¸ÕÀú µµÂøÇÏÁö´Â ¾Ê´Âµ¥, ±×·³¿¡µµ ºÒ±¸ÇÏ°í µ¥ÀÌÅÍÀÇ ¼ø¼¸¦ TCP¶ó´Â Åë½Å±Ô¾àÀÌ ¹Ù·ÎÀâ¾ÆÁֱ⠶§¹®¿¡ StreamÀÌ´Ù. ¹°·Ð UDP´Â ±×·±°ÍÀÌ º¸ÀåµÇÁö ¾Ê´Â´Ù.
socket()ÇÔ¼ö´Â ´ÜÁö Á¤¼ö°ª ÇÑ°³¸¦ µ¹·ÁÁִµ¥ (º¸ÅëÀº 4ÀÌ´Ù. ¿Ö³Ä¸é stdin, stdout, stderr °¡ °¢°¢ 1°³¾¿ Â÷ÁöÇÏ°í ÀÖ¾î¼ 4¹ø° fd °¡ µÈ´Ù) ¾ÕÀ¸·ÎÀÇ ¸ðµç Á¶ÀÛÀº ÀÌ Á¤¼ö°ªÀ» ÅëÇؼ ÇÏ°Ô µÈ´Ù (´Ù¸¥ ÇÔ¼ö¸¦ È£ÃâÇÒ¶§¸¶´Ù ÀÌ °ªÀ» ³Ñ°ÜÁà¾ß ÇÑ´Ù).
#include <sys/types.h>
#include <sys/socket.h>
int bind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen);
bind()ÇÔ¼ö´Â Socket°ú NameÀ» ¿¬°á½ÃÄÑ(binding) ÁÖ´Â ÇÔ¼öÀÌ´Ù(¿ª½Ã ¹«½¼ ¼Ò¸®³Ä! :@). socketÀÇ ¼º°ÝÀ» ¼³¸íÇÏ´Â sockaddr¶ó´Â ±¸Á¶Ã¼ÀÇ °ªµéÀ» ¾Õ¼ ¸¸µç fd °ª¿¡ ¿¬°á½ÃÄÑÁØ´Ù. ¿¹Á¦¸¦ º¸ÀÚ.
int port_listen = 8000;
struct sockaddr_in server_addr;
...
bzero((char *)&server_addr, sizeof(server_addr));
server_addr.sin_family = PF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(port_listen);
if((bind(fd, (struct sockaddr *)&server_addr, sizeof(server_addr))) < 0 ){
fprintf(stderr, "bind() error\n");
exit(-1);
}
sockaddr_in À̶ó´Â ±¸Á¶Ã¼°¡ µîÀåÇϴµ¥, bind¿¡¼ ¿¬°áÇÒ ¼ÒÄϼӼºÀ» ´ãÀ» ±¸Á¶Ã¼ÀÌ´Ù. ¿¹Á¦¿¡¼´Â '¾îµð¿¡¼³ª Á¢¼Ó°¡´ÉÇÑ'(INADDR_ANY) 8000 ¹ø Æ÷Æ®¸¦ listen Çϵµ·Ï ¼³Á¤ÇÏ°í ÀÖ´Ù. bind() ¿¡¼ ¿¡·¯°¡ ³ª´Â °æ¿ì´Â ù° ÀÌ¹Ì ´Ù¸¥ÇÁ·Î±×·¥ÀÌ ÀÌ Æ÷Æ®¸¦ ÀÌ¿ëÇÏ´Â °æ¿ì, µÑ° ´ç½ÅÀÇ ±ÇÇÑÀÌ ºÎÁ·ÇÑ °æ¿ìÀÌ´Ù. ½´ÆÛÀ¯Àú(root)¸¸ÀÌ 1024¹ø ¾Æ·¡ Æ÷Æ®¸¦ ¾µ ¼ö ÀÖ´Ù.
³»°¡ ¸¸µç ÇÁ·Î±×·¥ÀÌ ¿¹±âÄ¡¾ÊÀº ¿À·ù·Î Á¾·á Çعö¸±°æ¿ì¿¡ ±× ¾²·¹±â·Î ÀÎÇؼ bind() °¡ ½ÇÆÐÇÏ´Â °æ¿ì°¡ ¸¹Àºµ¥, ÀÌ·² °æ¿ì¿¡ À¯¿ëÇÑ Socket Àç»ç¿ë ¹æ¹ýÀÌ ÀÖ´Ù.
int one = 1;
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(one));
º¹ÀâÇÏ°Ô »ý°¢ÇÏÁö¸»°í ±×³É ÀÌ´ë·Î º¹»çÇؼ ¾²¸é µÈ´Ù. setsockopt()´Â ¼ÒÄÏÀÇ ´Ù¾çÇÑ ¿É¼ÇµéÀ» ¼³Á¤ÇÒ ¼ö Àִµ¥, ÇÊÀÚ´Â ´ÜÁö Æ÷Æ® Àç»ç¿ëÀ» À§Çؼ¸¸ »ç¿ëÇÑ´Ù --;
1.3 listen() #
#include <sys/socket.h>
int listen(int s, int backlog);
listen ÇÔ¼ö´Â, ÀÌÁ¦ Ŭ¶óÀ̾ðÆ®µéÀ» À§ÇØ ±Í¸¦ ±â¿ï¿©¶ó!ÇÏ°í ÃÖÁ¾¸í·ÉÀ» ³»¸®´Â °ÍÀÌ´Ù. ¿©Å±îÁö¸¦ Á¤¸®Çϸé, (1) socketÀ» »ý¼º (2) sockaddr_in ±¸Á¶Ã¼¸¦ ¸¸µé¾î ´ëÃæ ä¿ì°í (3) bind() ·Î 1°ú2 µÎ°³¸¦ ¹°í, (4) listen ÇÏ´Â ¼ø¼ÀÌ´Ù. ÀÌ·¸°Ô Çؼ ¼¹ö´Â ¿¬°áÀ» ¹Þ¾ÆµéÀÏ Áغñ°¡ µÈ´Ù. ½ÇÁ¦·Î Ŭ¶óÀ̾ðÆ®°¡ ¿¬°áÀ» ÇÏ¸é ¼¹ö´Â accept ÇÔ¼ö·Î ¿¬°áÀ» ¹Þ¾ÆµéÀÌ°í, Àû´çÇÑ ¶§¿¡ ÇØ´ç ¼ÒÄÏ¿¡¼ µ¥ÀÌÅ͸¦ ÀÐ°í ¶Ç Àû´çÇÑ ¶§¿¡ ¾²¸é µÇ´Â °Í.
¹Ù·Î ÀÌ Àû´çÇÑ ¶§¸¦ ±¸ÇöÇÏ´Â ¹æ¹ýÀÌ »ç½Ç ¼ÒÄÏ ÇÁ·Î±×·¡¹ÖÀÇ ÇÙ½ÉÀÌ´Ù!!
1.4 read() ¿Í write() #
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);
read(), write()´Â »ç½Ç ¼ÒÄÏ°ú´Â º°·Î »ó°üÀÌ ¾øÁö¸¸,
unixÀÇ ¸ðµç ÀåÄ¡´Â FILEÀÌ´Ù¶ó´Â öÇп¡ ÀÇÇØ ¼ÒÄÏ¿¡ µ¥ÀÌÅ͸¦ ¾²°Å³ª ÀÐÀ»¶§ »ç¿ëÇÑ´Ù. ÆÄÀÏ¿¡ ¾²°Å³ª ÀÐ´Â°Å¿Í ´Ù¸£Áö ¾Ê´Ù. ´Ù¸¸, ¼ÒÄÏ¿¬°áÀÌ ²÷±â°Å³ª ¿¡·¯°¡ ¹ß»ýÇßÀ» °æ¿ì ºÎ¼öÀûÀΠ󸮵éÀÌ ÇÊ¿äÇÏ´Ù.
#define MAX_BUF 1024
int nread;
char buf[MAX_BUF];
nread = read(fd, buf, MAX_BUF);
ÀÌ ¿¹Á¦´Â, fd°¡ °¡¸®Å°´Â °÷À¸·ÎºÎÅÍ µ¥ÀÌŸ¸¦ Àдµ¥ ÃÖ´ë MAX_BUF ¸¸Å¸¸ Àд´٠(´õ ¸¹ÀÌ ÀÖ´õ¶óµµ!!). ±× °á°ú°ªÀº ½ÇÁ¦ Àо ¹ÙÀÌÆ®¼öÀÌ´Ù. ´Ù¸¸, read()ÀÇ ¸®ÅÏ°ªÀÌ 0 ¶Ç´Â -1ÀÎ °æ¿ì¿¡ À¯ÀÇÇØ¾ß ÇÑ´Ù. ´ÙÀ½À» ÂùÂùÈ÷ Àß ÀоÀÚ.
On success, the number of bytes read is returned (zero indicates end of file), and the file position is advanced by this number.
It is not an error if this number is smaller than the number of bytes requested; this may happen for example because fewer
bytes are actually available right now (maybe because we were close to end-of-file, or because we are reading from a pipe,
or from a terminal), or because read() was interrupted by a signal. On error, -1 is returned, and errno is set appropriately.
In this case it is left unspecified whether the file position (if any) changes.
0ÀÎ °æ¿ì´Â ÆÄÀÏÀÇ ³¡, -1ÀÎ °æ¿ì´Â ¿¡·¯Àε¥, ¼ÒÄÏ¿¡¼ÀÇ ÆÄÀÏÀÇ ³¡À̶õ Åë½ÅÁ¾·á¸¦ ÀǹÌÇÒÅ×°í, ´ç¿¬È÷ ÇÁ·Î±×·¡¸Ó´Â socket Á¾·á 󸮸¦ ÇØ ÁÖ¾î¾ß ÇÑ´Ù. ¿¡·¯ÀÎ °æ¿ìµµ ¸¶Âù°¡Áö·Î Á¾·á󸮸¦ ÇØ ÁÖµµ·Ï ÇÏÀÚ (»óȲÀ» ´õ ÀÚ¼¼È÷ ±â·ÏÀ¸·Î ³²°Ü¼ ¿Ö ¿¡·¯°¡ ¹ß»ýÇß´ÂÁö ÃßÀûÇØ º¼ ¼öµµ ÀÖ´Ù).
if(nread <= 0) {
if(nread < 0){
// some error handling routine
}
close(fd);
}
write()ÀÇ °æ¿ì´Â Á»´õ ½Å°æ½á¾ß ÇÒ ÀÏÀÌ ¸¹´Ù. ±× Áß °¡ÀåÅ©°Ô ½Å°æÀ» ½á¾ß ÇÏ´Â °ÍÀº WOULDBLOCKÀÌ´Ù. ¿î¿µÃ¼Á¦ ³»ºÎÀûÀ¸·Î Åë½ÅÀ» À§ÇÑ ¹öÆÛ¸¦ °¡Áö°í Àִµ¥, ÀÌ ¹öÆÛº¸´Ù Å« µ¥ÀÌÅ͸¦ º¸³»·Á°í Çϰųª ÀÌ¹Ì °¡µæ Â÷ Àִµ¥ ¹«¾ð°¡¸¦ ´õ º¸³»·Á°í ÇÏ´Â °æ¿ì¿¡ WOULDBLOCKÀÌ ¹ß»ýÇÏ°Ô µÈ´Ù.
ÀÌ·±ÀÏÀº ÀϽÃÀûÀÎ Åë½ÅÁöü (ÈçÈ÷ '·¢') »óȲ¿¡¼ ÀϹÝÀûÀ¸·Î ¹ß»ýÇϴµ¥ ±×³É ¿¬°áÀ» ²÷¾î¹ö¸± ¼öµµ ¾ø°í, ¹öÆÛ°¡ ºñ¿öÁú¶§±îÁö ¹«ÀÛÁ¤ ±â´Ù¸± ¼öµµ ¾ø´Â ³ë¸©. ±×·¡¼ Send Buffering ±â¹ýÀ» ¾´´Ù. º¸³»¾ß ÇÒ µ¥ÀÌÅÍ°¡ ¹ß»ýÇÏ¸é ¹Ù·Î Àü¼ÛÇÏÁö ¾Ê°í ¾îÇø®ÄÉÀÌ¼Ç ¹öÆÛ¿¡ ³Ö¾îµÎ¸ç, Àû´çÇÑ ½ÃÁ¡¿¡¼ ½ÇÁ¦ Àü¼ÛÀ» ½ÃµµÇϵµ·Ï ÇÏ´Â ¹æ¹ýÀÌ´Ù. ÀÌ ±â¹ýÀº º°µµ ¹®¼·Î ´Ù½Ã ¾µ °èȹÀÌ´Ù.