안녕하세요! 소켓 프로그래밍 때문에 힘든가요? man 페이지로 공부하기가 너무 어려운가요? 멋진 인터넷 프로그래밍을 하고 싶지만 connect()를 호출하기 전에 bind()를 호출해야 하는지 알아내려고 한 무더기의 struct를 헤집고 다닐 시간이 없나요?
그런데 제가 그 귀찮은 일을 이미 다 해놨습니다. 그리고 그 정보를 여러분에게 공유하고 싶어서 안달이 나 있습니다. 제대로 찾아오셨습니다. 이 문서는 보통 수준의 C 프로그래머가 귀찮은 네트워킹을 처리할 수 있게 도와줄 것입니다.
그리고 이것도 보세요. 제가 드디어 미래의 기술을 따라잡았고(정말 겨우 시간을 맞췄죠) IPv6에 대한 안내를 갱신했습니다. 재밌게 보세요!
이 문서는 완전한 참고 문서가 아닌 튜토리얼로서 작성되었습니다. 아마도 이제 막 소켓 프로그래밍을 시작해서 발판이 필요한 사람이 읽기에 적합할 것입니다. 이것은 분명히 어떤 의미로든 완벽하고 완전한 소켓 프로그래밍 가이드는 아닙니다.
그럼에도 불구하고 이 문서를 읽고 나면 맨페이지가 이해되기 시작할 것입니다.
이 문서에 포함된 코드는 GNU의 gcc 컴파일러를 사용하는 리눅스 PC에서 컴파일되었습니다. 그러나 그 코드들은 gcc를 사용하는 거의 모든 플랫폼에서 빌드될 것입니다. 다만 Windows용 프로그램을 만들고 있다면 해당 사항이 없습니다. 그런 경우라면 윈도우 프로그래밍을 위한 절을 참고하세요.
이 문서의 공식 위치는 아래와 같습니다.
이곳에서 예제 코드와 이 안내서의 여러 언어로 된 번역본도 찾을 수 있습니다.
(사람들이 책이라고 부르는) 잘 제본된 인쇄본을 사고 싶다면 아래 링크에 방문하세요.
책을 구매해주신다면 글을 써서 먹고 사는 라이프 스타일을 유지하는 일에 도움이 되므로 감사하겠습니다.
Solaris 변종이나 SunOS를 위해서 컴파일할 때, 정확한 라이브러리에 링크하기 위해서 약간의 추가적인 명령줄 스위치를 지정해야 합니다. 그러기 위해서 컴파일 명령의 끝에 “-lnsl -lsocket -lresolv”를 아래와 같이 덧붙이세요.
$ cc -o server server.c -lnsl -lsocket -lresolv
여전히 오류가 있다면, 그 명령 뒤에 -lxnet를 덧붙여 보세요. 그것이 정확히 무엇을 하는지 저는 모르지만, 몇몇 사람들은 그렇게 해야 했던 것으로 보입니다.
setsockopt()을 호출하는 곳에서도 문제가 생길 수 있습니다. 제가 쓰는 리눅스 시스템과는 함수 원형이 다릅니다. 그러므로 아래의 코드 대신
int yes=1;이렇게 입력하세요.
char yes='1';저에게 Sun 시스템이 없으므로 위에 적은 내용들을 시험해 보지는 않았습니다. 저 내용들은 단지 사람들이 저에게 이메일로 알려준 것입니다.
역사적으로 안내서의 이 부분에서 저는 제가 그다지 좋아하지 않는다는 이유로 Windows를 조금 놀려 왔습니다. 하지만 그 뒤 Windows와 Microsoft라는 회사는 많이 나아졌습니다. Windows 10에 아래에서 말할 WSL을 곁들이면 꽤 괜찮은 운영체제가 됩니다. 딱히 크게 불평할 것도 없습니다.
음, 조금은 있습니다. 예를 들어 저는 이 글을 2025년에 2015년형 노트북에서 쓰고 있습니다. 예전에는 Windows 10을 돌리던 컴퓨터였습니다. 결국 너무 느려져서 Linux를 설치했고, 그 뒤로 계속 그렇게 쓰고 있습니다.
그런데 이제 Windows 11은 Windows 10보다 더 강력한 하드웨어를 요구하는 것 같습니다. 저는 그 점이 마음에 들지 않습니다. 운영체제는 가능한 한 뒤로 물러나 있어야 하고, 여러분에게 돈을 더 쓰라고 요구해서는 안 됩니다. 추가 CPU 성능은 운영체제가 아니라 응용프로그램을 위한 것이어야 합니다! 게다가 Microsoft는 여러분이 더 많은 광고를 원한다고 생각하는 모양입니다. 그것도 운영체제 안에요! 광고가 필요한가요? Windows 11이라면 가능합니다.
그래서… 저는 여전히 윈도우 대신 Linux1, BSD2, illumos3 또는 다른 종류의 유닉스를 써 보라고 권하고 싶습니다.
갑자기 흥분해서 연설을 해버렸네요.
하지만 사람들은 하던 대로 하고 싶어 하기 마련이고, 윈도우를 쓰는 분들은 이 문서의 정보가 Windows에도 약간의 차이만 빼면 보통 적용된다는 것을 알면 기뻐할 것입니다.
여러분이 진지하게 고려해봐야 할 것은 Windows Subsystem for Linux4입니다. 이것은 간단히 말하자면 Windows 10에 리눅스 VM 비슷한 것을 깔게 해 줍니다. 그렇게 하면 개발 환경을 갖출 수 있고, 예제 프로그램을 있는 그대로 빌드하고 실행할 수 있습니다. (역자 주: WSL은 Windows 11에서도 사용할 수 있습니다.)
여러분이 할 수 있는 다른 일은 Cygwin5을 설치하는 것입니다. 이것은 Windows를 위한 유닉스 도구 모음입니다. 그렇게 하면 예제 프로그램을 수정 없이 컴파일할 수 있다고 들었습니다만 직접 해 보지는 않았습니다.
여러분 중 몇몇은 순수한 Windows 방식으로 이 일을 하고 싶을지도 모르겠습니다. 그렇다면 아주 배짱이 두둑한 일이 되겠군요. 그렇게 하고 싶다면 당장 집 밖으로 가서 유닉스를 돌릴 컴퓨터를 사세요! 장난입니다. 요새는 윈도우에 (좀 더) 친화적으로 행동하려고 노력하고 있습니다.
좋습니다, 좋습니다. 이제 본론으로 돌아가겠습니다.
여러분이 할 일은 이렇습니다. 첫 번째로 제가 이 문서에서 언급하는 거의 모든 시스템 헤더 파일을 무시하세요. 그 대신 아래의 헤더 파일을 포함하세요.
#include <winsock2.h>
#include <ws2tcpip.h>winsock2는 “새로운”(대략 1994년 기준으로) 윈도우 소켓 라이브러리입니다.
불행하게도 여러분이 windows.h를 인클루드하면 그것이 자동으로 버전1인 오래된 winsock.h 를 끌어오고 winsock2.h와 충돌을 일으킬 것입니다. 정말 재밌지요.
그러므로 만약 windows.h를 인클루드해야 한다면 그것이 오래된 헤더를 포함하지 않도록 아래의 매크로를 정의해야 합니다.
#define WIN32_LEAN_AND_MEAN // 이렇게 적으세요.
#include <windows.h> // 이제 이것을 인클루드해도 됩니다.
#include <winsock2.h> // 이것도 인클루드해도 됩니다.잠깐! 소켓 라이브러리를 쓰기 전에 WSAStartup()을 호출해야 합니다. 이 함수에 사용하려는 Winsock 버전(예를 들어 2.2)을 인수로 넘기고 반환값을 확인해서 쓰고자 하는 버전이 사용 가능한지 확인해야 합니다.
그 작업을 하는 코드는 아래와 비슷할 것입니다.
#include <winsock2.h>
{
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
fprintf(stderr, "WSAStartup failed.\n");
exit(1);
}
if (LOBYTE(wsaData.wVersion) != 2 ||
HIBYTE(wsaData.wVersion) != 2)
{
fprintf(stderr,"Version 2.2 of Winsock not available.\n");
WSACleanup();
exit(2);
}저기 보이는 WSACleanup() 호출부를 주목하세요. Winsock 라이브러리를 다 쓴 후에 저것을 호출해야 합니다.
또한 컴파일러에게 ws2_32.lib라는 Winsock2 라이브러리를 링크하라고 말해줘야 합니다. VC++에서는 프로젝트 메뉴에서 설정으로 가서 링크 탭을 클릭하고 “오브젝트/라이브러리 모듈” 이라는 제목이 붙은 상자를 찾으세요. 그리고 거기에 “ws2_32.lib”나 여러분이 원하는 다른 라이브러리를 추가하세요. (역자 주: 최신 Visual Studio에서는 이 링크를 참고하세요.)
직접 해 본 것은 아닙니다.
그렇게 하고 나면, 이 튜토리얼의 나머지 예제들은 거의 그대로 쓸 수 있을 것입니다. 몇 가지 예외가 있는데 소켓을 닫기 위해서 close()를 쓸 수 없습니다. 대신 closesocket()을 써야 합니다. 또한 select()는 파일 설명자가 아닌 소켓 설명자에만 쓸 수 있습니다. (stdin의 0 같은 파일 설명자)
여러분이 쓸 수 있는 소켓 클래스도 있습니다. CSocket입니다. 자세한 정보는 컴파일러의 도움말 페이지를 참고하세요.
Winsock에 대한 정보를 더 얻고 싶다면 마이크로소프트의 공식 홈페이지를 참고하세요.
마지막으로 윈도우에는 fork()가 없다고 들었습니다. 불행히도 제 예제 코드 중 일부는 fork()를 사용합니다. 아마 그것을 동작하게 하려면 POSIX 라이브러리에 링크하거나 다른 작업이 필요할 것입니다. 아니면 CreateProcess()를 대신 쓸 수도 있습니다. fork()는 인수를 받지 않지만 CreateProcess()는 인수를 480억 개 정도 받습니다. 그게 부담스럽다면 CreateThread() 이 조금 더 쓰기 쉬울 겁니다. 불행히도 멀티스레딩에 대한 논의는 이 문서의 범위를 벗어납니다. 저는 이 정도까지밖에 말씀드릴 수가 없습니다.
정말 마지막으로, Steven Mitchell이 Winsock으로 변환한 많은 예제6도 확인해 볼 만합니다.
저는 대체로 이메일로 오는 문의사항에 답을 드리고자 하니 이메일 보내기를 주저하지 마세요. 그러나 응답을 보장하지는 못합니다. 저는 바쁜 삶을 살고 있고 제가 여러분이 가진 궁금증에 대답할 수 없는 때가 많이 있습니다. 그런 경우라면 저는 그 메시지를 그냥 삭제합니다. 개인적인 감정이 아닙니다. 그저 여러분이 필요로 하는 자세한 답을 할 시간이 없을 것이라 생각하기 때문입니다.
원칙적으로 질문이 복잡할수록 제가 응답할 가능성은 낮아질 것입니다. 메일을 보내기 전에 질문의 범위를 좁히고 적절한 정보(플랫폼, 컴파일러, 받은 오류 메시지, 문제 해결에 도움이 될 만한 다른 정보)를 첨부한다면 제 응답을 받을 확률이 올라갈 것입니다. 더 자세한 지침은 ESR의 문서인 How To Ask Questions The Smart Way7을 참고하세요.
여러분이 제 회신을 받지 못한다면, 문제를 더 파고들어보고, 답을 찾기 위해 노력해보세요. 그래도 확실한 답을 얻지 못했다면 그동안 알아낸 정보를 가지고 저에게 다시 메일을 보내세요. 어쩌면 제가 답을 드릴 수 있을지도 모릅니다.
저에게 메일을 보낼 때 이렇게 해라 저렇게 해라 말이 많았습니다만 이 안내서에 지난 몇 년 동안 보내주신 모든 칭찬에 정말로 감사한다는 사실을 말씀드리고 싶습니다. 그것은 정말로 정신적인 힘이 됩니다. 이 안내서가 좋은 일에 쓰였다는 말을 듣는 일은 저를 기쁘게 합니다. :-) 감사합니다!
이 웹사이트를 공개로든 사적으로든 미러링하는 것은 얼마든지 환영합니다. 이 웹사이트를 공개적으로 미러링하고 제가 메인 페이지에 링크를 걸게 하고 싶다면 beej@beej.us 로 메일을 보내주세요.
이 안내서를 다른 언어로 번역하고 싶다면 beej@beej.us에 메일을 보내주세요. 여러분의 번역본의 링크를 제 메인 페이지에 걸어두겠습니다. 여러분의 이름과 연락처 정보를 번역본에 추가하시는 것도 환영합니다.
이 원본 마크다운 문서는 UTF-8로 인코딩되었습니다.
아래의 Copyright, Distribution, and Legal 절에 있는 라이선스 제한 사항에 유의하세요.
제가 번역본을 호스트하길 바란다면 말씀해 주세요. 여러분이 호스트하길 원한다면 그것도 링크하겠습니다. 어느 쪽이든 좋습니다.
(Translator’s Note: This section has not been translated to keep its legal information.) (역자 주: 이 절은 법적 정보를 보존하기 위해 번역하지 않았습니다.)
Beej’s Guide to Network Programming is Copyright © 2019 Brian “Beej Jorgensen” Hall.
With specific exceptions for source code and translations, below, this work is licensed under the Creative Commons Attribution- Noncommercial- No Derivative Works 3.0 License. To view a copy of this license, visit
https://creativecommons.org/licenses/by-nc-nd/3.0/
or send a letter to Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA.
One specific exception to the “No Derivative Works” portion of the license is as follows: this guide may be freely translated into any language, provided the translation is accurate, and the guide is reprinted in its entirety. The same license restrictions apply to the translation as to the original guide. The translation may also include the name and contact information for the translator.
The C source code presented in this document is hereby granted to the public domain, and is completely free of any license restriction.
Educators are freely encouraged to recommend or supply copies of this guide to their students.
Unless otherwise mutually agreed by the parties in writing, the author offers the work as-is and makes no representations or warranties of any kind concerning the work, express, implied, statutory or otherwise, including, without limitation, warranties of title, merchantability, fitness for a particular purpose, noninfringement, or the absence of latent or other defects, accuracy, or the presence of absence of errors, whether or not discoverable.
Except to the extent required by applicable law, in no event will the author be liable to you on any legal theory for any special, incidental, consequential, punitive or exemplary damages arising out of the use of the work, even if the author has been advised of the possibility of such damages.
Contact beej@beej.us for more information.
이 안내서를 쓸 수 있도록 저를 과거에 도와주신, 그리고 미래에 도와주실 모든 분들에게 감사드립니다. 이 안내서를 만들기 위해 사용한 자유 소프트웨어와 패키지(GNU, Linux, Slackware, vim, Python, Inkscape, pandoc, 기타 등등…)를 만든 모든 분들에게 감사드립니다. 또한 이 안내서의 발전을 위한 제안을 해주시고 응원의 말씀을 보내주신 수천 명의 사람들에게 감사드립니다.
이 안내서를 컴퓨터 세계에서 저의 가장 위대한 영웅이자 영감을 주는 이들인 Donald Knuth, Bruce Schneier, W. Richard Stevens, Steve The Woz Wozniak, 독자 여러분, 그리고 모든 자유 및 공개 소프트웨어 커뮤니티에 바칩니다.
이 책은 GNU 도구를 갖춘 Arch Linux 시스템에서 Vim 편집기를 사용해서 Markdown 으로 작성되었습니다. 표지 “미술”과 다이어그램은 Inkscape로 작성되었습니다. Markdown은 Python과 Pandoc, XeLaTeX를 통해 HTML과 LaTeX/PDF로 변환되었습니다. 문서에는 Liberation 폰트를 사용했습니다. 툴체인은 전적으로 자유/공개 소프트웨어를 사용해서 구성했습니다.
원문의 첫 한국어 번역 버전은 박성호(tempter@fourthline.com)님이 1998/08/20(yyyy/MM/d)에 인터넷의 어딘가에 게시하신 것으로 보입니다. 현재는 KLDP에 있습니다.
원문의 두 번째 한국어 번역 버전은 김수봉(연락처 없음)님이 2003/12/15(yyyy/MM/d)에 KLDP에 게시하셨습니다. 첫 번역 문서를 html에서 wiki형태로 변환했다고 적혀 있습니다.
지금 읽고 계시는 세 번째 버전은 정민석(javalia.javalia@gmail.com)이 작업했으며, 2023년 5월 28일부터 작업했습니다.
원문의 번역본은 1998년에 최초로 한국어 버전이 작성된 이래로 한국인이 Socket 프로그래밍에 대해서 참고할 수 있는 문서 중 리눅스 맨페이지를 제외하면 가장 1차적인 문서였습니다. 실제로 많은 소켓 프로그래밍 관련 글과 출판된 책의 예제 코드도 이 문서의 것을 차용하고 있습니다. 원문은 세월이 흐르면서 조금씩 개정되어 내용이 상세해지고 IPv6에 대해서도 다루고 있으나 번역본은 20년 전의 모습으로 멈추어 있었습니다. 소켓 프로그래밍을 공부하던 시절 가장 큰 도움을 받은 문서의 번역본이 개정되지 않음을 안타깝게 생각해서 이렇게 새로운 번역본을 만들게 되었습니다. 이 글이 새로운 네트워크 라이브러리를 개발하는 프로그래머에게 도움이 되기를 바랍니다.
이 문서는 원문의 3.1.5 버전을 기반으로 번역되었습니다. 원문에 등장하는 고유명사는 해당 명사에 통용되는 한국어 번역이 없는 한 원어 그대로 실었습니다. 영어 일반명사는 음역을 기본으로 하였으나, 일부는 의역하기도 하였고 혼동을 줄이기 위해서 병기한 부분도 있습니다. 작업 과정에서 이전 번역자들의 원문을 유지하지는 못했습니다. 원문/번역본/새 번역본 사이의 대조/교정 작업은 개인적인 시간을 짜내서 진행하는 이 일에는 너무 큰 작업이었습니다. 이러한 사정으로 인해 이전 번역자들의 작업이 직접적으로 유지되지는 못하지만, 다른 프로그래머들을 위해 수십 년 전 글을 남기신 번역자 분들의 노력을 이어받고 그 작업을 존중하는 마음으로 다음 몇 년간 사람들이 읽을 수 있는 번역을 제공하기 위해 노력했습니다.
읽어주셔서 감사합니다.
원문 3.1.5 버전을 번역한 뒤 몇 해가 지나, 개정판을 다시 작업하게 되었습니다.
기존 번역판에 있던 수많은 오탈자와 잘못된 번역을 교정했으며, 기존에는 분량상의 이유로 번역하지 못했던 맨페이지 부분까지 번역했습니다. 기존과 마찬가지로 문서 전체에 걸쳐 Pretendard 폰트를 사용했으며 개정판에서는 코드 스니펫에 D2Coding 폰트를 사용해서 한글 주석이 조금 더 코드와 잘 어울리게 했습니다.
문서 전체를 개정하는 대규모 작업은 AI 덕분에 가능했습니다. 초판은 인터넷 검색과 수작업으로 번역했으나, 개정판은 거의 모든 부분을 AI의 도움으로 번역/교정했으며, 저는 최종적인 검수와 몇몇 부적절한 번역에 대한 조율 위주로 작업했습니다.
AI는 번역 작업을 쉽게 만들어 주었으며, 나아가 이런 안내 문서의 필요성마저 줄이고 있습니다. 소켓 프로그래밍에 대한 궁금증은 LLM도 답할 수 있고, 원문도 여러 LLM이 이미 학습한 것으로 보입니다.
이 책이 다루는 소켓 프로그래밍에 관심 있는 분들도 이제는 이런 문서보다는 LLM을 통해 학습하는 것이 더 자연스러우리라 생각합니다. 그런 만큼, 이런 시대에 번역 작업물의 개정안을 내는 것이 어떤 의미를 가지는지 생각하지 않을 수 없었습니다.
그러나 이 작업물은 인터넷에서 찾을 수 있는 가장 잘 짜인 소켓 프로그래밍 안내서 중 하나이며, 이 번역본은 그 안내서의 꽤 훌륭한 한국어 번역입니다. 누군가 이 안내서를 필요로 한다면, 개정 작업은 충분히 가치 있을 것입니다.
이 안내서를 직접 천천히 읽으셔도 좋고, LLM의 도움을 받아 훑어보셔도 좋습니다. 어떤 방식으로 보시든, 이 번역본이 여러분에게 도움이 되기를 바랍니다.
훌륭한 안내서를 수십 년간 다듬어온 원저자, 그리고 이 안내서의 원문과 번역문을 만들기 위해서 필요했던 지식과 도구를 만들어준 모든 사람들에게 감사의 마음을 전합니다.
읽어주셔서 감사합니다. - 2026년 7월 30일, 정민석.