├── .gitignore ├── README.md ├── materials ├── Lap_trinh_mang_IT4060.pdf ├── UNIX Network Programming, Volume 1, Third Edition, The Sockets Networking API.pdf ├── keir-davis-the-definitive-guide-to-linux-network-programming.pdf └── the-linux-programming-interface-michael-kerrisk.pdf └── samples ├── README.md ├── domain2ip.c ├── fork_client.c ├── fork_server.c ├── multithread_client.c ├── multithread_server.c ├── non_blocking_server.c ├── poll_client.c ├── poll_server.c ├── preforking_server.c ├── prethreading_server.c ├── select_client.c ├── select_server.c ├── select_server_v2.c ├── simple_client.c ├── simple_server.c ├── sniffer.c ├── ssl_client.c ├── tui_example.c ├── udp_receiver.c └── udp_sender.c /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Aa][Rr][Mm]/ 27 | [Aa][Rr][Mm]64/ 28 | bld/ 29 | [Bb]in/ 30 | [Oo]bj/ 31 | [Ll]og/ 32 | [Ll]ogs/ 33 | 34 | # Visual Studio 2015/2017 cache/options directory 35 | .vs/ 36 | # Uncomment if you have tasks that create the project's static files in wwwroot 37 | #wwwroot/ 38 | 39 | # Visual Studio 2017 auto generated files 40 | Generated\ Files/ 41 | 42 | # MSTest test Results 43 | [Tt]est[Rr]esult*/ 44 | [Bb]uild[Ll]og.* 45 | 46 | # NUnit 47 | *.VisualState.xml 48 | TestResult.xml 49 | nunit-*.xml 50 | 51 | # Build Results of an ATL Project 52 | [Dd]ebugPS/ 53 | [Rr]eleasePS/ 54 | dlldata.c 55 | 56 | # Benchmark Results 57 | BenchmarkDotNet.Artifacts/ 58 | 59 | # .NET Core 60 | project.lock.json 61 | project.fragment.lock.json 62 | artifacts/ 63 | 64 | # StyleCop 65 | StyleCopReport.xml 66 | 67 | # Files built by Visual Studio 68 | *_i.c 69 | *_p.c 70 | *_h.h 71 | *.ilk 72 | *.meta 73 | *.obj 74 | *.iobj 75 | *.pch 76 | *.pdb 77 | *.ipdb 78 | *.pgc 79 | *.pgd 80 | *.rsp 81 | *.sbr 82 | *.tlb 83 | *.tli 84 | *.tlh 85 | *.tmp 86 | *.tmp_proj 87 | *_wpftmp.csproj 88 | *.log 89 | *.vspscc 90 | *.vssscc 91 | .builds 92 | *.pidb 93 | *.svclog 94 | *.scc 95 | 96 | # Chutzpah Test files 97 | _Chutzpah* 98 | 99 | # Visual C++ cache files 100 | ipch/ 101 | *.aps 102 | *.ncb 103 | *.opendb 104 | *.opensdf 105 | *.sdf 106 | *.cachefile 107 | *.VC.db 108 | *.VC.VC.opendb 109 | 110 | # Visual Studio profiler 111 | *.psess 112 | *.vsp 113 | *.vspx 114 | *.sap 115 | 116 | # Visual Studio Trace Files 117 | *.e2e 118 | 119 | # TFS 2012 Local Workspace 120 | $tf/ 121 | 122 | # Guidance Automation Toolkit 123 | *.gpState 124 | 125 | # ReSharper is a .NET coding add-in 126 | _ReSharper*/ 127 | *.[Rr]e[Ss]harper 128 | *.DotSettings.user 129 | 130 | # TeamCity is a build add-in 131 | _TeamCity* 132 | 133 | # DotCover is a Code Coverage Tool 134 | *.dotCover 135 | 136 | # AxoCover is a Code Coverage Tool 137 | .axoCover/* 138 | !.axoCover/settings.json 139 | 140 | # Coverlet is a free, cross platform Code Coverage Tool 141 | coverage*[.json, .xml, .info] 142 | 143 | # Visual Studio code coverage results 144 | *.coverage 145 | *.coveragexml 146 | 147 | # NCrunch 148 | _NCrunch_* 149 | .*crunch*.local.xml 150 | nCrunchTemp_* 151 | 152 | # MightyMoose 153 | *.mm.* 154 | AutoTest.Net/ 155 | 156 | # Web workbench (sass) 157 | .sass-cache/ 158 | 159 | # Installshield output folder 160 | [Ee]xpress/ 161 | 162 | # DocProject is a documentation generator add-in 163 | DocProject/buildhelp/ 164 | DocProject/Help/*.HxT 165 | DocProject/Help/*.HxC 166 | DocProject/Help/*.hhc 167 | DocProject/Help/*.hhk 168 | DocProject/Help/*.hhp 169 | DocProject/Help/Html2 170 | DocProject/Help/html 171 | 172 | # Click-Once directory 173 | publish/ 174 | 175 | # Publish Web Output 176 | *.[Pp]ublish.xml 177 | *.azurePubxml 178 | # Note: Comment the next line if you want to checkin your web deploy settings, 179 | # but database connection strings (with potential passwords) will be unencrypted 180 | *.pubxml 181 | *.publishproj 182 | 183 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 184 | # checkin your Azure Web App publish settings, but sensitive information contained 185 | # in these scripts will be unencrypted 186 | PublishScripts/ 187 | 188 | # NuGet Packages 189 | *.nupkg 190 | # NuGet Symbol Packages 191 | *.snupkg 192 | # The packages folder can be ignored because of Package Restore 193 | **/[Pp]ackages/* 194 | # except build/, which is used as an MSBuild target. 195 | !**/[Pp]ackages/build/ 196 | # Uncomment if necessary however generally it will be regenerated when needed 197 | #!**/[Pp]ackages/repositories.config 198 | # NuGet v3's project.json files produces more ignorable files 199 | *.nuget.props 200 | *.nuget.targets 201 | 202 | # Microsoft Azure Build Output 203 | csx/ 204 | *.build.csdef 205 | 206 | # Microsoft Azure Emulator 207 | ecf/ 208 | rcf/ 209 | 210 | # Windows Store app package directories and files 211 | AppPackages/ 212 | BundleArtifacts/ 213 | Package.StoreAssociation.xml 214 | _pkginfo.txt 215 | *.appx 216 | *.appxbundle 217 | *.appxupload 218 | 219 | # Visual Studio cache files 220 | # files ending in .cache can be ignored 221 | *.[Cc]ache 222 | # but keep track of directories ending in .cache 223 | !?*.[Cc]ache/ 224 | 225 | # Others 226 | ClientBin/ 227 | ~$* 228 | *~ 229 | *.dbmdl 230 | *.dbproj.schemaview 231 | *.jfm 232 | *.pfx 233 | *.publishsettings 234 | orleans.codegen.cs 235 | 236 | # Including strong name files can present a security risk 237 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 238 | #*.snk 239 | 240 | # Since there are multiple workflows, uncomment next line to ignore bower_components 241 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 242 | #bower_components/ 243 | 244 | # RIA/Silverlight projects 245 | Generated_Code/ 246 | 247 | # Backup & report files from converting an old project file 248 | # to a newer Visual Studio version. Backup files are not needed, 249 | # because we have git ;-) 250 | _UpgradeReport_Files/ 251 | Backup*/ 252 | UpgradeLog*.XML 253 | UpgradeLog*.htm 254 | ServiceFabricBackup/ 255 | *.rptproj.bak 256 | 257 | # SQL Server files 258 | *.mdf 259 | *.ldf 260 | *.ndf 261 | 262 | # Business Intelligence projects 263 | *.rdl.data 264 | *.bim.layout 265 | *.bim_*.settings 266 | *.rptproj.rsuser 267 | *- [Bb]ackup.rdl 268 | *- [Bb]ackup ([0-9]).rdl 269 | *- [Bb]ackup ([0-9][0-9]).rdl 270 | 271 | # Microsoft Fakes 272 | FakesAssemblies/ 273 | 274 | # GhostDoc plugin setting file 275 | *.GhostDoc.xml 276 | 277 | # Node.js Tools for Visual Studio 278 | .ntvs_analysis.dat 279 | node_modules/ 280 | 281 | # Visual Studio 6 build log 282 | *.plg 283 | 284 | # Visual Studio 6 workspace options file 285 | *.opt 286 | 287 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 288 | *.vbw 289 | 290 | # Visual Studio LightSwitch build output 291 | **/*.HTMLClient/GeneratedArtifacts 292 | **/*.DesktopClient/GeneratedArtifacts 293 | **/*.DesktopClient/ModelManifest.xml 294 | **/*.Server/GeneratedArtifacts 295 | **/*.Server/ModelManifest.xml 296 | _Pvt_Extensions 297 | 298 | # Paket dependency manager 299 | .paket/paket.exe 300 | paket-files/ 301 | 302 | # FAKE - F# Make 303 | .fake/ 304 | 305 | # CodeRush personal settings 306 | .cr/personal 307 | 308 | # Python Tools for Visual Studio (PTVS) 309 | __pycache__/ 310 | *.pyc 311 | 312 | # Cake - Uncomment if you are using it 313 | # tools/** 314 | # !tools/packages.config 315 | 316 | # Tabs Studio 317 | *.tss 318 | 319 | # Telerik's JustMock configuration file 320 | *.jmconfig 321 | 322 | # BizTalk build output 323 | *.btp.cs 324 | *.btm.cs 325 | *.odx.cs 326 | *.xsd.cs 327 | 328 | # OpenCover UI analysis results 329 | OpenCover/ 330 | 331 | # Azure Stream Analytics local run output 332 | ASALocalRun/ 333 | 334 | # MSBuild Binary and Structured Log 335 | *.binlog 336 | 337 | # NVidia Nsight GPU debugger configuration file 338 | *.nvuser 339 | 340 | # MFractors (Xamarin productivity tool) working folder 341 | .mfractor/ 342 | 343 | # Local History for Visual Studio 344 | .localhistory/ 345 | 346 | # BeatPulse healthcheck temp database 347 | healthchecksdb 348 | 349 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 350 | MigrationBackup/ 351 | 352 | # Ionide (cross platform F# VS Code tools) working folder 353 | .ionide/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Website cung cấp cho sinh viên: 2 | * Slide bài giảng và tài liệu tham khảo, trong thư mục **materials** 3 | * Một số ví dụ minh họa các mô hình lý thuyết học trên lớp, trong thư mục **samples**. 4 | -------------------------------------------------------------------------------- /materials/Lap_trinh_mang_IT4060.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lebavui/network_programming/6ce05f4c3b260cc5622e3d437821aea0c6f5fff3/materials/Lap_trinh_mang_IT4060.pdf -------------------------------------------------------------------------------- /materials/UNIX Network Programming, Volume 1, Third Edition, The Sockets Networking API.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lebavui/network_programming/6ce05f4c3b260cc5622e3d437821aea0c6f5fff3/materials/UNIX Network Programming, Volume 1, Third Edition, The Sockets Networking API.pdf -------------------------------------------------------------------------------- /materials/keir-davis-the-definitive-guide-to-linux-network-programming.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lebavui/network_programming/6ce05f4c3b260cc5622e3d437821aea0c6f5fff3/materials/keir-davis-the-definitive-guide-to-linux-network-programming.pdf -------------------------------------------------------------------------------- /materials/the-linux-programming-interface-michael-kerrisk.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lebavui/network_programming/6ce05f4c3b260cc5622e3d437821aea0c6f5fff3/materials/the-linux-programming-interface-michael-kerrisk.pdf -------------------------------------------------------------------------------- /samples/README.md: -------------------------------------------------------------------------------- 1 | # Các ví dụ minh họa môn học 2 | -------------------------------------------------------------------------------- /samples/domain2ip.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | // Ví dụ về phân giải tên miền thành địa chỉ IP 7 | // Tham số nhập vào từ dòng lệnh là tên miền cần phân giải 8 | 9 | int main(int argc, char* argv[]) { 10 | 11 | // Kiểm tra tham số có được nhập vào không 12 | if (argc != 2) 13 | { 14 | printf("Tham so khong hop le.\n"); 15 | return 1; 16 | } 17 | 18 | // Khai báo con trỏ kết quả 19 | struct addrinfo *res, *p; 20 | 21 | int ret = getaddrinfo(argv[1], "http", NULL, &res); 22 | if (ret != 0 || res == NULL) 23 | { 24 | printf("Failed to get IP.\n"); 25 | return 1; 26 | } 27 | 28 | // Duyệt danh sách kết quả và in ra địa chỉ IP 29 | p = res; 30 | while (p != NULL) { 31 | if (p->ai_family == AF_INET) // IPv4 32 | { 33 | printf("IPv4\n"); 34 | struct sockaddr_in addr; 35 | memcpy(&addr, p->ai_addr, p->ai_addrlen); 36 | printf("IP: %s\n", inet_ntoa(addr.sin_addr)); 37 | } 38 | else if (p->ai_family == AF_INET6) // IPv6 39 | { 40 | printf("IPv6\n"); 41 | char buf[64]; 42 | struct sockaddr_in6 addr6; 43 | memcpy(&addr6, p->ai_addr, p->ai_addrlen); 44 | printf("IP: %s\n", inet_ntop(p->ai_family, &addr6.sin6_addr, buf, sizeof(buf))); 45 | } 46 | p = p->ai_next; 47 | } 48 | 49 | // Giải phóng con trỏ kết quả 50 | freeaddrinfo(res); 51 | 52 | return 0; 53 | } -------------------------------------------------------------------------------- /samples/fork_client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | int main() { 11 | // Khai báo socket 12 | int client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 13 | 14 | // Khai báo địa chỉ của server 15 | struct sockaddr_in addr; 16 | addr.sin_family = AF_INET; 17 | addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 18 | addr.sin_port = htons(9000); 19 | 20 | // Kết nối đến server 21 | int res = connect(client, (struct sockaddr *)&addr, sizeof(addr)); 22 | if (res == -1) { 23 | printf("Khong ket noi duoc den server!\n"); 24 | return 1; 25 | } 26 | 27 | char buf[256]; 28 | 29 | // Tạo tiến trình mới 30 | int cid = fork(); 31 | if (cid == 0) 32 | { 33 | // Tiến trình con, nhận dữ liệu từ bàn phím 34 | while (1) 35 | { 36 | fgets(buf, sizeof(buf), stdin); 37 | send(client, buf, strlen(buf), 0); 38 | if (strncmp(buf, "exit", 4) == 0) 39 | break; 40 | } 41 | } 42 | else 43 | { 44 | // Tiến trình cha, nhận dữ liệu từ socket 45 | while (1) 46 | { 47 | int ret = recv(client, buf, sizeof(buf), 0); 48 | if (ret <= 0) 49 | break; 50 | buf[ret] = 0; 51 | printf("Received: %s\n", buf); 52 | } 53 | } 54 | 55 | // Kết thúc, đóng socket 56 | close(client); 57 | 58 | // Dừng các tiến trình 59 | killpg(0, SIGKILL); 60 | 61 | return 0; 62 | } -------------------------------------------------------------------------------- /samples/fork_server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | // Hàm xử lý tín hiệu SIGCHLD 12 | void signalHandler(int signo) 13 | { 14 | pid_t pid; 15 | int stat; 16 | printf("signo = %d\n", signo); 17 | pid = wait(&stat); 18 | printf("child %d terminated.\n", pid); 19 | return; 20 | } 21 | 22 | int main() 23 | { 24 | // Hiển thị số tiến trình tối đa có thể tạo 25 | // struct rlimit lim; 26 | // getrlimit(RLIMIT_NPROC, &lim); 27 | // printf("Soft limit: %ld\n", lim.rlim_cur); 28 | // printf("Hard limit: %ld\n", lim.rlim_max); 29 | 30 | // Tạo socket chờ kết nối 31 | int listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 32 | 33 | // Khai báo cấu trúc địa chỉ của server 34 | struct sockaddr_in addr; 35 | addr.sin_family = AF_INET; 36 | addr.sin_addr.s_addr = htonl(INADDR_ANY); 37 | addr.sin_port = htons(9000); 38 | 39 | // Gắn địa chỉ với socket và chuyển sang chờ kết nối 40 | bind(listener, (struct sockaddr *)&addr, sizeof(addr)); 41 | listen(listener, 5); 42 | 43 | pid_t pid; 44 | 45 | // Đăng ký xử lý tín hiệu SIGCHLD 46 | signal(SIGCHLD, signalHandler); 47 | 48 | while (1) 49 | { 50 | printf("Waiting for new client\n"); 51 | int client = accept(listener, NULL, NULL); 52 | printf("New client accepted: %d\n", client); 53 | 54 | // Tạo tiến trình cho kết nối mới 55 | if ((pid = fork()) == 0) 56 | { 57 | // Trong tiến trình con 58 | 59 | // Đóng socket listener vì không dùng đến 60 | close(listener); 61 | 62 | // Nhận và xử lý dữ liệu 63 | char buf[256]; 64 | while (1) 65 | { 66 | int ret = recv(client, buf, sizeof(buf), 0); 67 | if (ret <= 0) 68 | break; 69 | buf[ret] = 0; 70 | printf("Received from client %d: %s\n", client, buf); 71 | send(client, buf, strlen(buf), 0); 72 | } 73 | 74 | // Đóng kết nối 75 | close(client); 76 | 77 | // Kết thúc tiến trình con 78 | exit(0); 79 | } 80 | 81 | // Trong tiến trình cha, đóng socket client do không dùng đến 82 | close(client); 83 | } 84 | 85 | return 0; 86 | } -------------------------------------------------------------------------------- /samples/multithread_client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | void* thread_proc(void *arg); 11 | 12 | int main() 13 | { 14 | // Tạo socket kết nối đến server 15 | int client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 16 | 17 | // Khai báo cấu trúc địa chỉ server 18 | struct sockaddr_in addr; 19 | addr.sin_family = AF_INET; 20 | addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 21 | addr.sin_port = htons(9000); 22 | 23 | // Kết nối đến server 24 | if (connect(client, (struct sockaddr *)&addr, sizeof(addr))) 25 | { 26 | printf("Khong the ket noi den server.\n"); 27 | return 1; 28 | } 29 | 30 | // Tạo luồng mới 31 | pthread_t thread_id; 32 | if (pthread_create(&thread_id, NULL, thread_proc, (void *)&client)) 33 | { 34 | printf("Khong the tao luong!\n"); 35 | return 1; 36 | } 37 | 38 | // Chuyển luồng sang chế độ tự giải phóng 39 | pthread_detach(thread_id); 40 | 41 | char buf[256]; 42 | 43 | // Trong luồng chính, chờ dữ liệu từ bàn phím 44 | while (1) 45 | { 46 | fgets(buf, sizeof(buf), stdin); 47 | send(client, buf, strlen(buf), 0); 48 | if (strncmp(buf, "exit", 4) == 0) 49 | break; 50 | } 51 | 52 | close(client); 53 | return 0; 54 | } 55 | 56 | void* thread_proc(void *arg) 57 | { 58 | // Trong luồng con, chờ dữ liệu từ socket 59 | 60 | printf("child thread created.\n"); 61 | int client = *(int *)arg; 62 | char buf[256]; 63 | while (1) 64 | { 65 | int len = recv(client, buf, sizeof(buf), 0); 66 | if (len <= 0) 67 | break; 68 | buf[len] = 0; 69 | printf("%s\n", buf); 70 | } 71 | close(client); 72 | printf("child thread finished.\n"); 73 | return 0; 74 | } -------------------------------------------------------------------------------- /samples/multithread_server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | void* thread_proc(void *arg); 11 | 12 | int main() 13 | { 14 | // Hiển thị số luồng tối đa có thể tạo 15 | // struct rlimit lim; 16 | // getrlimit(RLIMIT_NPROC, &lim); 17 | // printf("Soft limit: %ld\n", lim.rlim_cur); 18 | // printf("Hard limit: %ld\n", lim.rlim_max); 19 | 20 | // Tạo socket chờ kết nối 21 | int listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 22 | 23 | // Khai báo cấu trúc địa chỉ server chờ ở cổng 9000 24 | struct sockaddr_in addr; 25 | addr.sin_family = AF_INET; 26 | addr.sin_addr.s_addr = htonl(INADDR_ANY); 27 | addr.sin_port = htons(9000); 28 | 29 | // Gắn địa chỉ với socket và chuyển sang trạng thái chờ kết nối 30 | bind(listener, (struct sockaddr *)&addr, sizeof(addr)); 31 | listen(listener, 5); 32 | 33 | pthread_t thread_id; 34 | 35 | while (1) 36 | { 37 | printf("Waiting for new client ...\n"); 38 | // Chấp nhận kết nối mới 39 | int client = accept(listener, NULL, NULL); 40 | if (client == -1) 41 | continue; 42 | printf("New client connected: %d\n", client); 43 | 44 | // Tạo luồng để xử lý yêu cầu từ client 45 | int ret = pthread_create(&thread_id, NULL, thread_proc, (void *)&client); 46 | if (ret != 0) 47 | { 48 | printf("Could not create thread!\n"); 49 | } 50 | 51 | // Yêu cầu luồng tự giải phóng khi kết thúc 52 | pthread_detach(thread_id); 53 | // Ưu tiên luồng mới tạo bắt đầu chạy 54 | sched_yield(); 55 | } 56 | 57 | return 0; 58 | } 59 | 60 | void* thread_proc(void *arg) 61 | { 62 | // Luồng xử lý yêu cầu từ client 63 | 64 | printf("child thread created.\n"); 65 | int client = *(int *)arg; 66 | char buf[2048]; 67 | while (1) 68 | { 69 | int len = recv(client, buf, sizeof(buf), 0); 70 | if (len <= 0) 71 | break; 72 | buf[len] = 0; 73 | printf("%s", buf); 74 | } 75 | close(client); 76 | printf("child thread finished.\n"); 77 | } -------------------------------------------------------------------------------- /samples/non_blocking_server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | /// @brief Hàm xóa client khỏi mảng 12 | /// @param clients Mảng client đang kết nối đến server 13 | /// @param pNumClients Địa chỉ biến chứa số lượng client 14 | /// @param index Thứ tự của phần tử cần xóa 15 | void removeClient(int *clients, int *pNumClients, int index) 16 | { 17 | if (index < *pNumClients - 1) 18 | clients[index] = clients[*pNumClients - 1]; 19 | *pNumClients = *pNumClients - 1; 20 | } 21 | 22 | int main() 23 | { 24 | // Tạo socket 25 | int listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 26 | if (listener == -1) 27 | { 28 | perror("socket() failed"); 29 | return 1; 30 | } 31 | 32 | // Chuyển socket sang trạng thái bất đồng bộ 33 | unsigned long ul = 1; 34 | ioctl(listener, FIONBIO, &ul); 35 | 36 | // Khai báo cấu trúc địa chỉ server 37 | struct sockaddr_in addr; 38 | addr.sin_family = AF_INET; 39 | addr.sin_addr.s_addr = htonl(INADDR_ANY); 40 | addr.sin_port = htons(9000); 41 | 42 | // Gắn địa chỉ với socket 43 | if (bind(listener, (struct sockaddr *)&addr, sizeof(addr))) 44 | { 45 | perror("bind() failed"); 46 | return 1; 47 | } 48 | 49 | if (listen(listener, 5)) 50 | { 51 | perror("listen() failed"); 52 | return 1; 53 | } 54 | 55 | int clients[64]; 56 | int numClients = 0; 57 | char buf[256]; 58 | 59 | while (1) 60 | { 61 | // Chấp nhận kết nối 62 | int client = accept(listener, NULL, NULL); 63 | if (client == -1) 64 | { 65 | // Nếu lỗi không phải do đang chờ kết nối 66 | if (errno != EWOULDBLOCK) 67 | { 68 | perror("accept() failed"); 69 | return 1; 70 | } 71 | else 72 | { 73 | // Nếu lỗi do đang chờ kết nối thì bỏ qua, thực hiện công việc khác 74 | } 75 | } 76 | else 77 | { 78 | // Nếu có kết nối mới thì thêm vào mảng và chuyển sang trạng thái bất đồng bộ 79 | printf("New client connected: %d\n", client); 80 | clients[numClients++] = client; 81 | ul = 1; 82 | ioctl(client, FIONBIO, &ul); 83 | } 84 | 85 | // Kiểm tra các client có truyền dữ liệu không 86 | for (int i = 0; i < numClients; i++) 87 | { 88 | int ret = recv(clients[i], buf, sizeof(buf), 0); 89 | if (ret == -1) 90 | { 91 | if (errno != EWOULDBLOCK) 92 | { 93 | // Nếu lỗi không phải do đang chờ dữ liệu 94 | // Xóa client khỏi mảng 95 | // Chuyển sang kiểm tra kết nối khác 96 | perror("recv() failed"); 97 | close(clients[i]); 98 | removeClient(clients, &numClients, i--); 99 | continue; 100 | } 101 | else 102 | { 103 | // Nếu lỗi do đang chờ dữ liệu thì bỏ qua 104 | } 105 | } 106 | else if (ret == 0) 107 | { 108 | // Nếu kế nối bị đóng, thì xóa client khỏi mảng 109 | printf("client disconnected.\n"); 110 | close(clients[i]); 111 | removeClient(clients, &numClients, i--); 112 | continue; 113 | } 114 | else 115 | { 116 | // Xử lý dữ liệu nhận được 117 | // Thêm ký tự kết thúc xâu và in ra màn hình 118 | if (ret < sizeof(buf)) 119 | buf[ret] = 0; 120 | puts(buf); 121 | // Trả lại kết quả cho client 122 | send(clients[i], buf, strlen(buf), 0); 123 | } 124 | } 125 | } 126 | 127 | close(listener); 128 | 129 | return 0; 130 | } -------------------------------------------------------------------------------- /samples/poll_client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | int main() { 11 | // Khai báo socket 12 | int client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 13 | 14 | // Khai báo địa chỉ của server 15 | struct sockaddr_in addr; 16 | addr.sin_family = AF_INET; 17 | addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 18 | addr.sin_port = htons(9000); 19 | 20 | // Kết nối đến server 21 | int res = connect(client, (struct sockaddr *)&addr, sizeof(addr)); 22 | if (res == -1) { 23 | printf("Khong ket noi duoc den server!\n"); 24 | return 1; 25 | } 26 | 27 | // Mảng cấu trúc thăm dò 28 | struct pollfd fds[2]; 29 | 30 | // Thêm descriptor của sự kiện bàn phím 31 | fds[0].fd = STDIN_FILENO; 32 | fds[0].events = POLLIN; 33 | 34 | // Thêm descriptor của sự kiện socket 35 | fds[1].fd = client; 36 | fds[1].events = POLLIN; 37 | 38 | char buf[256]; 39 | 40 | while (1) 41 | { 42 | // Chờ đến khi sự kiện xảy ra, không sử dụng timeout 43 | int ret = poll(fds, 2, -1); 44 | 45 | // Nếu sự kiện là có dữ liệu từ bàn phím 46 | if (fds[0].revents & POLLIN) 47 | { 48 | fgets(buf, sizeof(buf), stdin); 49 | send(client, buf, strlen(buf), 0); 50 | 51 | // Nếu nhập "exit" thì kết thúc 52 | if (strncmp(buf, "exit", 4) == 0) 53 | break; 54 | } 55 | 56 | // Nếu sự kiện là có dữ liệu từ socket 57 | if (fds[1].revents & POLLIN) 58 | { 59 | ret = recv(client, buf, sizeof(buf), 0); 60 | if (ret <= 0) 61 | break; 62 | buf[ret] = 0; 63 | printf("Received: %s\n", buf); 64 | } 65 | } 66 | 67 | close(client); 68 | 69 | return 0; 70 | } -------------------------------------------------------------------------------- /samples/poll_server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #define MAX_CLIENTS 1024 13 | 14 | // Hàm xóa client ra khỏi mảng thăm dò 15 | void removeClient(struct pollfd *fds, nfds_t *nfds, int index) 16 | { 17 | if (index < *nfds - 1) 18 | fds[index] = fds[*nfds - 1]; 19 | *nfds = *nfds - 1; 20 | } 21 | 22 | int main() 23 | { 24 | // struct rlimit lim; 25 | // getrlimit(RLIMIT_NOFILE, &lim); 26 | // printf("Soft limit: %ld\n", lim.rlim_cur); 27 | // printf("Hard limit: %ld\n", lim.rlim_max); 28 | 29 | int listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 30 | 31 | struct sockaddr_in addr; 32 | addr.sin_family = AF_INET; 33 | addr.sin_addr.s_addr = INADDR_ANY; 34 | addr.sin_port = htons(9000); 35 | 36 | bind(listener, (struct sockaddr *)&addr, sizeof(addr)); 37 | listen(listener, 5); 38 | 39 | // Mảng thăm dò sự kiện 40 | struct pollfd fds[MAX_CLIENTS]; 41 | nfds_t nfds = 1; 42 | 43 | // Thêm socket listener vào mảng 44 | fds[0].fd = listener; 45 | fds[0].events = POLLIN; 46 | 47 | char buf[2048]; 48 | 49 | while (1) 50 | { 51 | // Chờ sự kiện xảy ra hoặc hết giờ 52 | printf("Waiting for new event.\n"); 53 | int ret = poll(fds, nfds, 5000); 54 | if (ret < 0) 55 | { 56 | printf("poll() failed.\n"); 57 | return 1; 58 | } 59 | if (ret == 0) 60 | { 61 | printf("Timed out.\n"); 62 | continue; 63 | } 64 | 65 | // Nếu sự kiện có yêu cầu kết nối 66 | if (fds[0].revents & POLLIN) 67 | { 68 | int client = accept(listener, NULL, NULL); 69 | 70 | if (nfds < MAX_CLIENTS) 71 | { 72 | printf("New client connected %d\n", client); 73 | // Lưu vào mảng để thăm dò 74 | fds[nfds].fd = client; 75 | fds[nfds].events = POLLIN; 76 | nfds++; 77 | } 78 | else 79 | { 80 | // Đã vượt quá số kết nối tối đa 81 | close(client); 82 | } 83 | } 84 | 85 | // Kiểm tra sự kiện dữ liệu đến socket 86 | for (int i = 1; i < nfds; i++) 87 | if (fds[i].revents & (POLLIN | POLLERR)) 88 | { 89 | ret = recv(fds[i].fd, buf, sizeof(buf), 0); 90 | if (ret <= 0) 91 | { 92 | printf("Client %d disconnected\n", fds[i].fd); 93 | // Remove from clients 94 | removeClient(fds, &nfds, i); 95 | i--; 96 | continue; 97 | } 98 | buf[ret] = 0; 99 | printf("Received data from client %d: %s\n", fds[i].fd, buf); 100 | } 101 | } 102 | 103 | return 0; 104 | } -------------------------------------------------------------------------------- /samples/preforking_server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | int main() 11 | { 12 | // Tạo socket 13 | int listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 14 | 15 | // Khai báo cấu trúc địa chỉ server 16 | struct sockaddr_in addr; 17 | addr.sin_family = AF_INET; 18 | addr.sin_addr.s_addr = htonl(INADDR_ANY); 19 | addr.sin_port = htons(9000); 20 | 21 | // Gắn địa chỉ với socket 22 | bind(listener, (struct sockaddr *)&addr, sizeof(addr)); 23 | listen(listener, 5); 24 | 25 | int num_processes = 8; 26 | char buf[256]; 27 | 28 | // Tạo trước các tiến trình, mỗi tiến trình lặp lại công việc chấp nhận kết nối và xử lý yêu cầu của client 29 | for (int i = 0; i < num_processes; i++) 30 | if (fork() == 0) 31 | while(1) 32 | { 33 | // Chờ kết nối 34 | int client = accept(listener, NULL, NULL); 35 | printf("New client accepted in process %d: %d\n", client, getpid()); 36 | 37 | // Chờ dữ liệu từ client 38 | int ret = recv(client, buf, sizeof(buf), 0); 39 | if (ret <= 0) 40 | continue; 41 | 42 | // Xử lý dữ liệu, trả lại kết quả cho client 43 | buf[ret] = 0; 44 | printf("Received from client %d: %s\n", client, buf); 45 | send(client, buf, strlen(buf), 0); 46 | 47 | // Đóng kết nối 48 | close(client); 49 | } 50 | 51 | // Đợi vô thời hạn, đảm bảo chương trình tiếp tục hoạt động 52 | wait(NULL); 53 | 54 | return 0; 55 | } -------------------------------------------------------------------------------- /samples/prethreading_server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | void* thread_proc(void *arg); 10 | 11 | int main() 12 | { 13 | // Tạo socket chờ kết nối 14 | int listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 15 | 16 | // Khai báo cấu trúc địa chỉ server 17 | struct sockaddr_in addr; 18 | addr.sin_family = AF_INET; 19 | addr.sin_addr.s_addr = htonl(INADDR_ANY); 20 | addr.sin_port = htons(9000); 21 | 22 | // Gắn địa chỉ với socket 23 | bind(listener, (struct sockaddr *)&addr, sizeof(addr)); 24 | listen(listener, 5); 25 | 26 | int num_threads = 8; 27 | pthread_t thread_id; 28 | 29 | // Tạo trước các luồng 30 | for (int i = 0; i < num_threads; i++) 31 | { 32 | int ret = pthread_create(&thread_id, NULL, thread_proc, &listener); 33 | if (ret != 0) 34 | printf("Could not create new thread.\n"); 35 | sched_yield(); 36 | } 37 | 38 | // Đợi vô thời hạn, đảm bảo chương trình tiếp tục hoạt động 39 | pthread_join(thread_id, NULL); 40 | return 0; 41 | } 42 | 43 | void* thread_proc(void *arg) 44 | { 45 | int listener = *(int *)arg; 46 | char buf[256]; 47 | 48 | while (1) 49 | { 50 | // Chờ kết nối 51 | int client = accept(listener, NULL, NULL); 52 | printf("New client %d accepted in thread %ld with pid %d\n", client, pthread_self(), getpid()); 53 | 54 | // Chờ dữ liệu từ client 55 | int ret = recv(client, buf, sizeof(buf), 0); 56 | if (ret <= 0) 57 | continue; 58 | 59 | // Xử lý dữ liệu, trả lại kết quả cho client 60 | buf[ret] = 0; 61 | printf("Received from client %d: %s\n", client, buf); 62 | send(client, buf, strlen(buf), 0); 63 | 64 | // Đóng kết nối 65 | close(client); 66 | } 67 | 68 | return NULL; 69 | } -------------------------------------------------------------------------------- /samples/select_client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | int main() { 10 | // Khai báo socket client 11 | int client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 12 | 13 | // Khai báo địa chỉ server 14 | struct sockaddr_in addr; 15 | addr.sin_family = AF_INET; 16 | addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 17 | addr.sin_port = htons(9000); 18 | 19 | // Thực hiện kết nối đến server 20 | int res = connect(client, (struct sockaddr *)&addr, sizeof(addr)); 21 | if (res == -1) { 22 | printf("Khong ket noi duoc den server!\n"); 23 | return 1; 24 | } 25 | 26 | // Khai báo tập fdset 27 | fd_set fdread; 28 | char buf[256]; 29 | 30 | while (1) 31 | { 32 | // Khởi tạo lại tập fdread 33 | FD_ZERO(&fdread); 34 | 35 | // Gắn các descriptor vào tập fdread 36 | FD_SET(STDIN_FILENO, &fdread); 37 | FD_SET(client, &fdread); 38 | 39 | // Chờ đến khi sự kiện xảy ra 40 | int ret = select(client + 1, &fdread, NULL, NULL, NULL); 41 | if (ret == -1) 42 | { 43 | perror("select() failed"); 44 | break; 45 | } 46 | 47 | // Kiểm tra sự kiện có dữ liệu từ bàn phím 48 | if (FD_ISSET(STDIN_FILENO, &fdread)) 49 | { 50 | fgets(buf, sizeof(buf), stdin); 51 | send(client, buf, strlen(buf), 0); 52 | 53 | // Nếu nhập "exit" thì kết thúc 54 | if (strncmp(buf, "exit", 4) == 0) 55 | break; 56 | } 57 | 58 | // Kiểm tra sự kiện có dữ liệu truyền đến qua socket 59 | if (FD_ISSET(client, &fdread)) 60 | { 61 | ret = recv(client, buf, sizeof(buf), 0); 62 | 63 | // Nếu ngắt kết nối thì kết thúc 64 | if (ret <= 0) 65 | break; 66 | 67 | buf[ret] = 0; 68 | printf("Received: %s\n", buf); 69 | } 70 | } 71 | 72 | // Kết thúc, đóng socket 73 | close(client); 74 | 75 | return 0; 76 | } -------------------------------------------------------------------------------- /samples/select_server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define MAX_CLIENTS FD_SETSIZE 12 | 13 | // Xóa client ra khỏi mảng 14 | void removeClient(int *clients, int *numClients, int clientIndex) 15 | { 16 | if (clientIndex < *numClients - 1) 17 | clients[clientIndex] = clients[*numClients - 1]; 18 | *numClients = *numClients - 1; 19 | } 20 | 21 | int main() 22 | { 23 | int listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 24 | 25 | struct sockaddr_in addr; 26 | addr.sin_family = AF_INET; 27 | addr.sin_addr.s_addr = INADDR_ANY; 28 | addr.sin_port = htons(9000); 29 | 30 | bind(listener, (struct sockaddr *)&addr, sizeof(addr)); 31 | listen(listener, 5); 32 | 33 | fd_set fdread; 34 | 35 | // Mảng clients lưu các socket đã được chấp nhận 36 | // Sử dụng trong việc thăm dò sự kiện 37 | int clients[MAX_CLIENTS]; 38 | int numClients = 0; 39 | 40 | // Cấu trúc thời gian đợi 41 | struct timeval tv; 42 | tv.tv_sec = 5; 43 | tv.tv_usec = 0; 44 | 45 | char buf[2048]; 46 | 47 | while (1) 48 | { 49 | // Khởi tạo lại tập fdread 50 | FD_ZERO(&fdread); 51 | 52 | // Gắn các socket listener và clients vào tập fdread 53 | // maxdp lưu giá trị descriptor lớn nhất 54 | FD_SET(listener, &fdread); 55 | int maxdp = listener; 56 | for (int i = 0; i < numClients; i++) 57 | { 58 | FD_SET(clients[i], &fdread); 59 | if (clients[i] > maxdp) 60 | maxdp = clients[i]; 61 | } 62 | 63 | // Khởi tạo lại giá trị cấu trúc thời gian 64 | tv.tv_sec = 5; 65 | tv.tv_usec = 0; 66 | 67 | // Chờ đến khi sự kiện xảy ra hoặc hết giờ 68 | printf("Waiting for new event.\n"); 69 | int ret = select(maxdp + 1, &fdread, NULL, NULL, &tv); 70 | if (ret < 0) 71 | { 72 | printf("select() failed.\n"); 73 | return 1; 74 | } 75 | if (ret == 0) 76 | { 77 | printf("Timed out.\n"); 78 | continue; 79 | } 80 | 81 | // Thăm dò sự kiện có yêu cầu kết nối 82 | if (FD_ISSET(listener, &fdread)) 83 | { 84 | int client = accept(listener, NULL, NULL); 85 | 86 | if (numClients < MAX_CLIENTS) 87 | { 88 | printf("New client connected %d\n", client); 89 | // Lưu vào mảng để thăm dò sự kiện 90 | clients[numClients] = client; 91 | numClients++; 92 | } 93 | else 94 | { 95 | // Đã vượt quá số kết nối tối đa 96 | close(client); 97 | } 98 | } 99 | 100 | // Thăm dò sự kiện có dữ liệu truyền đến các socket client 101 | for (int i = 0; i < numClients; i++) 102 | if (FD_ISSET(clients[i], &fdread)) 103 | { 104 | ret = recv(clients[i], buf, sizeof(buf), 0); 105 | if (ret <= 0) 106 | { 107 | printf("Client %d disconnected\n", clients[i]); 108 | // Xóa client khỏi mảng 109 | removeClient(clients, &numClients, i); 110 | i--; 111 | continue; 112 | } 113 | buf[ret] = 0; 114 | printf("Received data from client %d: %s\n", clients[i], buf); 115 | } 116 | } 117 | 118 | return 0; 119 | } -------------------------------------------------------------------------------- /samples/select_server_v2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | int main() 12 | { 13 | int listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 14 | 15 | struct sockaddr_in addr; 16 | addr.sin_family = AF_INET; 17 | addr.sin_addr.s_addr = INADDR_ANY; 18 | addr.sin_port = htons(9000); 19 | 20 | bind(listener, (struct sockaddr *)&addr, sizeof(addr)); 21 | listen(listener, 5); 22 | 23 | // Khai báo tập fdread chứa các socket và tập fdtest để thăm dò sự kiện 24 | fd_set fdread, fdtest; 25 | 26 | // Cấu trúc thời gian đợi 27 | struct timeval tv; 28 | char buf[2048]; 29 | 30 | // Khởi tạo tập fdread 31 | FD_ZERO(&fdread); 32 | 33 | // Gắn socket listener vào tập fdread 34 | FD_SET(listener, &fdread); 35 | 36 | while (1) 37 | { 38 | // Tập fdtest để thăm dò sự kiện, giữ nguyên các socket trong tập fdread 39 | fdtest = fdread; 40 | 41 | // Khởi tạo lại giá trị cấu trúc thời gian 42 | tv.tv_sec = 5; 43 | tv.tv_usec = 0; 44 | 45 | // Chờ đến khi sự kiện xảy ra hoặc hết giờ 46 | printf("Waiting for new event.\n"); 47 | int ret = select(FD_SETSIZE, &fdtest, NULL, NULL, &tv); 48 | if (ret < 0) 49 | { 50 | printf("select() failed.\n"); 51 | return 1; 52 | } 53 | if (ret == 0) 54 | { 55 | printf("Timed out.\n"); 56 | continue; 57 | } 58 | 59 | for (int i = 0; i < FD_SETSIZE; i++) 60 | if (FD_ISSET(i, &fdtest)) 61 | { 62 | if (i == listener) 63 | { 64 | // Socket listener có sự kiện yêu cầu kết nối 65 | int client = accept(listener, NULL, NULL); 66 | 67 | if (client < FD_SETSIZE) 68 | { 69 | printf("New client connected %d\n", client); 70 | 71 | // Thêm vào tập fdread 72 | FD_SET(client, &fdread); 73 | } 74 | else 75 | { 76 | // Đã vượt quá số kết nối tối đa 77 | close(client); 78 | } 79 | } 80 | else 81 | { 82 | // Socket client có sự kiện nhận dữ liệu 83 | ret = recv(i, buf, sizeof(buf), 0); 84 | if (ret <= 0) 85 | { 86 | printf("Client %d disconnected\n", i); 87 | FD_CLR(i, &fdread); 88 | } 89 | else 90 | { 91 | buf[ret] = 0; 92 | printf("Received data from client %d: %s\n", i, buf); 93 | } 94 | } 95 | } 96 | } 97 | 98 | return 0; 99 | } -------------------------------------------------------------------------------- /samples/simple_client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | int main() { 11 | // Khai báo socket kết nối đến server 12 | int client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 13 | 14 | // Khai báo địa chỉ của server 15 | struct sockaddr_in addr; 16 | addr.sin_family = AF_INET; 17 | addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 18 | addr.sin_port = htons(9000); 19 | 20 | // Kết nối đến server 21 | int res = connect(client, (struct sockaddr *)&addr, sizeof(addr)); 22 | if (res == -1) { 23 | perror("connect() failed"); 24 | return 1; 25 | } 26 | 27 | // Gửi tin nhắn đến server 28 | char *msg = "Hello server"; 29 | send(client, msg, strlen(msg), 0); 30 | 31 | // Nhận tin nhắn từ server 32 | char buf[2048]; 33 | int len = recv(client, buf, sizeof(buf), 0); 34 | 35 | // Nếu kết nối bị đóng hoặc bị lỗi thì kết thúc chương trình 36 | if (len <= 0) 37 | { 38 | printf("recv() failed.\n"); 39 | return 1; 40 | } 41 | 42 | // Xử lý dữ liệu nhận được 43 | // Thêm ký tự kết thúc xâu và in ra màn hình 44 | if (len < sizeof(buf)) 45 | buf[len] = 0; 46 | printf("Data received: %s\n", buf); 47 | 48 | // Kết thúc, đóng socket 49 | close(client); 50 | 51 | return 0; 52 | } -------------------------------------------------------------------------------- /samples/simple_server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | int main() 11 | { 12 | // Tạo socket chờ kết nối 13 | int listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 14 | if (listener == -1) 15 | { 16 | perror("socket() failed"); 17 | return 1; 18 | } 19 | 20 | // Khai báo cấu trúc địa chỉ của server 21 | struct sockaddr_in addr; 22 | addr.sin_family = AF_INET; 23 | addr.sin_addr.s_addr = htonl(INADDR_ANY); 24 | addr.sin_port = htons(9000); 25 | 26 | // Gắn socket với cấu trúc địa chỉ 27 | if (bind(listener, (struct sockaddr *)&addr, sizeof(addr))) 28 | { 29 | perror("bind() failed"); 30 | return 1; 31 | } 32 | 33 | // Chuyển socket sang trạng thái chờ kết nối 34 | if (listen(listener, 5)) 35 | { 36 | perror("listen() failed"); 37 | return 1; 38 | } 39 | 40 | printf("waiting for a new client ...\n"); 41 | 42 | // Chờ và chấp nhận kết nối 43 | int client = accept(listener, NULL, NULL); 44 | if (client == -1) 45 | { 46 | perror("accept() failed"); 47 | return 1; 48 | } 49 | printf("new client connected: %d\n", client); 50 | 51 | // Nhận dữ liệu từ client 52 | char buf[256]; 53 | int ret = recv(client, buf, sizeof(buf), 0); 54 | 55 | // Kiểm tra kết nối có bị đóng hoặc hủy không 56 | if (ret <= 0) 57 | { 58 | printf("recv() failed.\n"); 59 | return 1; 60 | } 61 | 62 | // Thêm ký tự kết thúc xâu và in ra màn hình 63 | if (ret < sizeof(buf)) 64 | buf[ret] = 0; 65 | puts(buf); 66 | 67 | // Gửi dữ liệu sang client 68 | send(client, buf, strlen(buf), 0); 69 | 70 | // Đóng kết nối 71 | close(client); 72 | close(listener); 73 | 74 | return 0; 75 | } -------------------------------------------------------------------------------- /samples/sniffer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | int main() 11 | { 12 | int sock_raw = socket(AF_INET, SOCK_RAW, IPPROTO_TCP); 13 | if (sock_raw < 0) 14 | { 15 | printf("Failed to create socket: %d\n", errno); 16 | return 1; 17 | } 18 | 19 | unsigned char *buffer = (unsigned char *)malloc(65535); 20 | int saddr_size , data_size; 21 | struct sockaddr saddr; 22 | 23 | unsigned char ip_protocol; 24 | 25 | while (1) 26 | { 27 | data_size = recvfrom(sock_raw, buffer, 65535, 0, &saddr, &saddr_size); 28 | if (data_size < 0) 29 | { 30 | printf("Recvfrom error, failed to get packets\n"); 31 | return 1; 32 | } 33 | // Process the packet 34 | printf("Data size: %d\n", data_size); 35 | for (int i = 0; i < 40; i++) 36 | printf("%x ", buffer[i]); 37 | printf("\n"); 38 | memcpy(&ip_protocol, buffer + 9, 1); 39 | if (ip_protocol == 1) 40 | printf("ICMP\n"); 41 | else if (ip_protocol == 6) 42 | printf("TCP\n"); 43 | else if (ip_protocol == 17) 44 | printf("UDP\n"); 45 | } 46 | 47 | close(sock_raw); 48 | return 0; 49 | } -------------------------------------------------------------------------------- /samples/ssl_client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | int main() { 11 | SSL_library_init(); 12 | 13 | const SSL_METHOD *my_ssl_method = TLS_client_method(); 14 | 15 | SSL_CTX *my_ssl_context = SSL_CTX_new(my_ssl_method); 16 | if (my_ssl_context == NULL) { 17 | printf("ERROR to create SSL context.\n"); 18 | return 1; 19 | } 20 | 21 | SSL *my_ssl = SSL_new(my_ssl_context); 22 | if (my_ssl == NULL) { 23 | printf("ERROR to create SSL.\n"); 24 | return 1; 25 | } 26 | 27 | int client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 28 | 29 | struct sockaddr_in addr; 30 | addr.sin_family = AF_INET; 31 | addr.sin_addr.s_addr = inet_addr("111.65.250.2"); 32 | addr.sin_port = htons(443); 33 | 34 | connect(client, (struct sockaddr *)&addr, sizeof(addr)); 35 | 36 | SSL_set_fd(my_ssl, client); 37 | 38 | if (SSL_connect(my_ssl) <= 0) { 39 | printf("ERROR to SSL connect.\n"); 40 | return 1; 41 | } 42 | 43 | char buf[2048] = "GET / HTTP/1.1\r\nHost: vnexpress.net\r\n\r\n"; 44 | SSL_write(my_ssl, buf, strlen(buf)); 45 | 46 | int len = SSL_read(my_ssl, buf, sizeof(buf)); 47 | if (len < sizeof(buf)) 48 | buf[len] = 0; 49 | 50 | printf("Read %d bytes: %s\n", len, buf); 51 | 52 | SSL_shutdown(my_ssl); 53 | SSL_free(my_ssl); 54 | SSL_CTX_free(my_ssl_context); 55 | close(client); 56 | } -------------------------------------------------------------------------------- /samples/tui_example.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() 6 | { 7 | initscr(); 8 | 9 | WINDOW *input_border = newwin(3, 50, 0, 0); 10 | wborder(input_border, '|', '|', '-', '-', '+', '+', '+', '+'); 11 | wrefresh(input_border); 12 | 13 | WINDOW *log_border = newwin(16, 50, 3, 0); 14 | wborder(log_border, '|', '|', '-', '-', '+', '+', '+', '+'); 15 | wrefresh(log_border); 16 | 17 | WINDOW *input_win = newwin(1, 48, 1, 1); 18 | wrefresh(input_win); 19 | 20 | WINDOW *log_win = newwin(14, 48, 4, 1); 21 | scrollok(log_win, TRUE); 22 | wrefresh(log_win); 23 | 24 | char str[256]; 25 | 26 | while (1) 27 | { 28 | wclear(input_win); 29 | wrefresh(input_win); 30 | 31 | wgetstr(input_win, str); 32 | if (strcmp(str, "exit") == 0) break; 33 | 34 | wprintw(log_win, "%s\n", str); 35 | wrefresh(log_win); 36 | } 37 | 38 | delwin(input_border); 39 | delwin(log_border); 40 | delwin(input_win); 41 | delwin(log_win); 42 | 43 | endwin(); 44 | return 0; 45 | } -------------------------------------------------------------------------------- /samples/udp_receiver.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | int main() 11 | { 12 | // Tạo socket theo giao thức UDP 13 | int receiver = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 14 | 15 | // Khai báo địa chỉ bên nhận 16 | struct sockaddr_in addr; 17 | addr.sin_family = AF_INET; 18 | addr.sin_addr.s_addr = htonl(INADDR_ANY); 19 | addr.sin_port = htons(9090); 20 | 21 | bind(receiver, (struct sockaddr *)&addr, sizeof(addr)); 22 | 23 | // Nhận tin nhắn 24 | char buf[16]; 25 | while (1) 26 | { 27 | int ret = recvfrom(receiver, buf, sizeof(buf), 0, NULL, NULL); 28 | if (ret == -1) 29 | { 30 | printf("recvfrom() failed\n"); 31 | break; 32 | } 33 | else 34 | { 35 | buf[ret] = 0; 36 | printf("%d - %s\n", ret, buf); 37 | } 38 | } 39 | 40 | return 0; 41 | } -------------------------------------------------------------------------------- /samples/udp_sender.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | int main() 10 | { 11 | // Tạo socket theo giao thức UDP 12 | int sender = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 13 | 14 | // Khai báo địa chỉ bên nhận 15 | struct sockaddr_in addr; 16 | addr.sin_family = AF_INET; 17 | addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 18 | addr.sin_port = htons(9090); 19 | 20 | // Gửi tin nhắn 21 | char buf[256]; 22 | while (1) 23 | { 24 | printf("Enter message: "); 25 | fgets(buf, sizeof(buf), stdin); 26 | sendto(sender, buf, strlen(buf), 0, (struct sockaddr *)&addr, sizeof(addr)); 27 | } 28 | 29 | return 0; 30 | } --------------------------------------------------------------------------------