Skip to content

Latest commit

ย 

History

9 Commits

Folders and files

NameName
Last commit message
Last commit date
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

Multi-Threaded_Chat-Application

Develop the Chat Application multithreaded

Abstract

Raw CLI chatting application for C language socket API practice.

Envirment

OS & Kernel

os&kernel

GCC

gcc

GNU Make

make

Build

make

  • Change directory to root (Multi-Threaded_Chat-Application directory)
  • Just type make

build

remove (make clean)

  • Change directory to root (Multi-Threaded_Chat-Application directory)
  • Just type make clean

clean

Explain the details

File structure

structure

  • bin: executable binary.
  • img: report images.
  • include: header and backend function source file. (After build, then object file exist too.)
  • src: main(frontend) source file. (After build, then object file exist too.)

Source

๋ชจ๋“  ์†Œ์Šค์—์„œ ์—๋Ÿฌ์— ๊ฐ•๋ ฅํ•˜๊ฒŒ ๋Œ€์‘ํ•˜์—ฌ assertion์„ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค.

Chat source

include/chat.h

chatHdr

client์™€ server์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๋ชจ๋“  ํ—ค๋”๋ฅผ ๋ฏธ๋ฆฌ ์„ ์–ธํ•˜์˜€๊ณ , ๊ณตํ†ต์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ํ•จ์ˆ˜๋“ค์— ๋Œ€ํ•œ ์„ ์–ธ์ด ์กด์žฌํ•œ๋‹ค.

๋˜ ๋ณ„๋„๋กœ ์„œ๋ฒ„๋‹จ์—์„œ ์ˆ˜์šฉํ•  ์ˆ˜ ์žˆ๋Š” client์˜ ์ตœ๋Œ€ ํฌ๊ธฐ๋ฅผ ์ €์žฅํ•˜๋Š” macro์™€ pthread์˜ ์ž์› ๊ฒฝ์Ÿ ์ƒํƒœ(race condition)์ทจ์•ฝ์ ์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•œ pthread mutex๋„ ์กด์žฌํ•œ๋‹ค.

๋˜, ์ž๋ฃŒํ˜•์„ ๋ณด๊ธฐ ํŽธํ•˜๊ฒŒ ์ƒˆ๋กœ ์ •์˜ํ–ˆ๋‹ค.

setup()

setup

File stream clean up.

readBuf()

readBuf

Get the input message string. ๋ฌดํ•œ์ • ์ž…๋ ฅ์„ ๋ฐ›๊ธฐ ์œ„ํ•ด, 1byte์”ฉ ์ž…๋ ฅ์„ ๋ฐ›๋‹ค๊ฐ€ ์ผ์ • ํฌ๊ธฐ ์ด์ƒ์˜ ์ž…๋ ฅ์„ ๋ฐ›๊ฒŒ๋˜์—ˆ๋‹ค๋ฉด ๊ณต๊ฐ„์„ ์žฌํ• ๋‹นํ•˜๊ณ  readํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ์ž…๋ ฅ์„ ๊ณ„์† ๋ฐ›๋Š”๋‹ค. ๊ฐœํ–‰์ด๋‚˜ NULL byte๊ฐ€ ์ž…๋ ฅ๋  ๋•Œ๊นŒ์ง€ ๋ฐ˜๋ณตํ•˜๊ณ , ๋ฌด์กฐ๊ฑด ๋ฌธ์ž์—ด์˜ ๋งˆ์ง€๋ง‰์ด '\n\0'์ด ๋˜๋„๋ก ๊ตฌ์„ฑํ•œ๋‹ค. readํ•จ์ˆ˜๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ int read(int fd, void *buf, size_t count);์˜ ํ˜•ํƒœ๋กœ ๊ตฌ์„ฑ์ด ๋˜์–ด์žˆ๋‹ค. 1๋ฒˆ์งธ ์ธ์ž์— ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ(์—ฌ๊ธฐ์„œ๋Š” 0, stdin์˜ fd), 2๋ฒˆ์งธ ์ธ์ž์—๋Š” ๋ฒ„ํผ์˜ ์ฃผ์†Œ, 3๋ฒˆ์งธ ์ธ์ž์—๋Š” ์ž…๋ ฅ๋ฐ›์„ ๊ธธ์ด๋ฅผ ๋„˜๊ฒจ๋ฐ›๋Š”๋‹ค. readํ•จ์ˆ˜๋Š” ๋„˜๊ฒจ๋ฐ›์€ fd์˜ ํŒŒ์ผ๋กœ๋ถ€ํ„ฐ count๋งŒํผ buf์— ์ž…๋ ฅ์„ ๋ฐ›๋Š” ํ•จ์ˆ˜๋‹ค. ํ•จ์ˆ˜๊ฐ€ ์„ฑ๊ณต์ ์œผ๋กœ ์ž‘๋™ํ•˜๋ฉด ์ž…๋ ฅ๋ฐ›์€ ๊ธธ์ด๋ฅผ, ์‹คํŒจํ•œ๋‹ค๋ฉด error number๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

sendMsg() & recvMsg()

communication sendMsg send๋ผ๋Š” TCP/IP ํ†ต์‹  API๋ฅผ ํ†ตํ•ด ์ž…๋ ฅ๋ฐ›์€ msg๋ฅผ ์ „์†กํ•œ๋‹ค.
sendํ•จ์ˆ˜๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ssize_t send(int sockfd, const void *buf, size_t len, int flags);์˜ ํ˜•ํƒœ๋กœ ํ•จ์ˆ˜ ํ˜•์‹์ด ๊ตฌํ˜„๋˜์–ด์žˆ๋‹ค. ์ฒซ ๋ฒˆ์งธ ์ธ์ž๋กœ ๋ฐ›์•„์˜ค๋Š” sockfd์— ์—ฐ๊ฒฐ๋œ ์†Œ์ผ“์— buf๋ฅผ len๋งŒํผ tcp/ip protocol์„ ํ†ตํ•ด ์ „์†กํ•œ๋‹ค. flag๊ฐ’์€ ์†ก์‹  ๋ฐฉ์‹์„ ์„ค์ •ํ•œ๋‹ค.

recvMsg recv๋ผ๋Š” TCP/IP ํ†ต์‹  API๋ฅผ ํ†ตํ•ด msg๋ฅผ ์ „์†ก๋ฐ›๋Š”๋‹ค. recvํ•จ์ˆ˜๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ssize_t recv(int sockfd, void *buf, size_t len, int flags);์˜ ํ˜•ํƒœ๋กœ ํ•จ์ˆ˜ ํ˜•์‹์ด ๊ตฌํ˜„๋˜์–ด์žˆ๋‹ค. ์ฒซ ๋ฒˆ์งธ ์ธ์ž๋กœ ๋ฐ›์•„์˜ค๋Š” sockfd์— ์—ฐ๊ฒฐ๋œ ์†Œ์ผ“์—์„œ ์ž…๋ ฅ์„ buf์— len๋งŒํผ tcp/ip protocol์„ ํ†ตํ•ด ๋ฐ›์•„์˜จ๋‹ค. flag๊ฐ’์€ ์ˆ˜์‹  ๋ฐฉ์‹์„ ์„ค์ •ํ•œ๋‹ค. ์ด ๊ณผ์ •์—์„œ ๋ฐ›๋Š” msg์˜ ํฌ๊ธฐ ์ œํ•œ์ด ์—†๋„๋ก readBuf์˜ ๋ฃจํ‹ด์„ ์ฐธ์กฐํ•œ๋‹ค. ์ดํ›„์—๋Š” ๋ฐ›์•„์˜จ msg๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

Server source

include/server.h

s_struct

DISCONNECT_STR๋Š” ํด๋ผ์ด์–ธํŠธ์˜ ์—ฐ๊ฒฐ์ด ์ข…๋ฃŒ๋์„ ๋•Œ, ์—ฐ๊ฒฐ ์ข…๋ฃŒ๋ฅผ ์•Œ๋ฆฌ๊ธฐ ์œ„ํ•œ string์„ ์‚ฌ์ „์— ์ •์˜ํ•ด๋†“์€ macro๋‹ค.

๋˜, client์™€ sender๋ผ๋Š” ๊ตฌ์กฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. client๊ตฌ์กฐ์ฒด๋Š” ๊ฐ๊ฐ ์—ฐ๊ฒฐ๋  5๊ฐœ์˜ ํด๋ผ์ด์–ธํŠธ ์ •๋ณด๋ฅผ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•ด ์กด์žฌํ•˜๊ณ , sender๊ตฌ์กฐ์ฒด๋Š” ๋ฐ›์•„์˜จ ๋ฉ”์‹œ์ง€๋ฅผ ์ „ ์†Œ์ผ“์— ๋‹ค ์ „์†กํ•˜๊ธฐ ์œ„ํ•ด ๋ฐ›์•„์˜จ ๋ฉ”์‹œ์ง€์— ๋Œ€ํ•œ ์ •๋ณด(sender fd, sender name, message value, used)๋ฅผ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•ด ์กด์žฌํ•œ๋‹ค.

include/server.c

validateArgv(int argc, const char* argv[])

s_validator

์„œ๋ฒ„ ๋ฐ”์ด๋„ˆ๋ฆฌ ์ธ์ž์˜ ์œ ํšจ์„ฑ์„ ๊ฒ€์ฆํ•˜๋Š” ํ•จ์ˆ˜๋‹ค. ์œ ํšจ์„ฑ ๊ฒ€์ฆ์— ์‹คํŒจํ•˜๋ฉด, 1์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ์ž์„ธํ•œ ์„ค๋ช…์€ ์ƒ๋žตํ•˜๊ฒ ๋‹ค.

getPort(int argc, const char* argv[])

s_getPort

์•ž์— ์„ค๋ช…ํ•œ validateArgv๋ฅผ ํ†ตํ•ด ์ธ์ž์˜ ์œ ํšจ์„ฑ์„ ๊ฒ€์ฆํ•œ ๋’ค, strtoullํ•จ์ˆ˜๋กœ port๊ฐ’์„ int๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

void printAddrInfo(struct sockaddr_in *addr)

s_printAddrInfo

sockaddr_in๊ตฌ์กฐ์ฒด ํฌ์ธํ„ฐ๋ฅผ ์ธ์ž๋กœ ๋„˜๊ฒจ๋ฐ›๊ณ , ํ•ด๋‹น ์ธ์ž ๊ฐ’์˜ ์ •๋ณด๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค. inet_ntopํ•จ์ˆ˜๋Š” addr->sin_addr์— ์ €์žฅ๋œ ip address์˜ ๊ฐ’์„ string์œผ๋กœ ๋ณ€ํ™˜ํ•ด์ค€๋‹ค.

int connectSocket(int port)

s_connectSocket

์ „์ฒด์ ์ธ ๋ฃจํ‹ด์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค. ๋งŒ์•ฝ ์ „์—ญ๋ณ€์ˆ˜ SOCKFD์— ๊ฐ’์ด ์กด์žฌํ•œ๋‹ค๋ฉด,

  • socket ์ƒ์„ฑ
  • ์ง€์ •๋œ ์ •๋ณด๋กœ addr ์ •๋ณด ํ• ๋‹น
  • bind API๋ฅผ ํ†ตํ•ด์„œ addr๋ณ€์ˆ˜ ๊ฐ’์„ ์ƒ์„ฑ๋œ socket์— ์ ์šฉ
  • listen API๋ฅผ ํ†ตํ•ด์„œ socket์„ passive opening ์ƒํƒœ๋กœ ๋ณ€๊ฒฝ (์™ธ๋ถ€ ์—ฐ๊ฒฐ ํ—ˆ์šฉ -> tcp 3-way handshake๊ณผ์ •์„ (syn -> syn, ack -> ack) ๋ชจ๋‘ ์ฒ˜๋ฆฌํ•œ๋‹ค.)
  • ์ „์—ญ๋ณ€์ˆ˜ SOCKFD์— ์ƒ์„ฑ๋œ socket fd ํ• ๋‹น.
  • accpet API๋ฅผ ํ†ตํ•ด, ์—ฐ๊ฒฐ์„ ์ˆ˜์‹ ๋ฐ›์•˜์„ ๊ฒฝ์šฐ, ์‹ค์ œ๋กœ ์—ฐ๊ฒฐ์„ ์šฉ์ธ. (passive open ์ƒํƒœ์˜€์„ ๊ฒฝ์šฐ์—๋Š” ์—ฐ๊ฒฐ ์ˆ˜๋ฆฝ ๋ฐ ๋ฉ”์‹œ์ง€ ์ˆ˜์‹ ์„ ํ–ˆ์„ ๊ฒฝ์šฐ queue์— ์ €์žฅํ•ด๋†“์ง€๋งŒ accept๋œ ์ดํ›„์—๋Š” queue์— ๋‹ด๊ธด ๊ฒƒ๋“ค์„ ๋ชจ๋‘ ๊บผ๋‚ด์™€์„œ communication์„ ์ง„ํ–‰ํ•œ๋‹ค.)
  • ์ตœ์ข…์ ์œผ๋กœ ์—ฐ๊ฒฐ์ด ์ˆ˜๋ฆฝ๋œ client์— ๋Œ€ํ•œ ์ •๋ณด ์ถœ๋ ฅ

๋งŒ์•ฝ SOCKFD๊ฐ€ ์ด๋ฏธ ๊ฐ’์ด ํ• ๋‹น๋˜์—ˆ๋‹ค๋ฉด,

  • ์œ„์˜ ๋ชจ๋“  ๊ณผ์ •์„ ์ƒ๋žตํ•˜๊ณ  accept ๊ณผ์ •๋งŒ ์ง„ํ–‰ํ•œ๋‹ค. (์–ด์ฒ˜ํ”ผ ์ด๋ฏธ socket์€ passive open ์ƒํƒœ์ผ ๊ฒƒ์ด๋ฏ€๋กœ)

src/server.c

void exitHdlr(int sig)

s_signalHdlr

ํ•ธ๋“ค๋Ÿฌ ํ•จ์ˆ˜ ์ด์ „์— send ๋ฐ recv routineํ•จ์ˆ˜์— ๋Œ€ํ•œ ์„ ์–ธ์ด ์กด์žฌํ•˜๋ฉฐ, ์•ž์„œ ์„ค๋ช…ํ•œ ๋‘ ๊ตฌ์กฐ์ฒด์˜ ์ „์—ญ๋ณ€์ˆ˜ ์„ ์–ธ์ด ์กด์žฌํ•œ๋‹ค. CLIENTS๋ฐฐ์—ด์€ CLIENT_MAX ๋งŒํผ์˜ ์‚ฌ์ด์ฆˆ๋ฅผ ๊ฐ–๋Š”๋‹ค. ์ดํ•˜ ํ•ธ๋“ค๋Ÿฌ๋Š” ๋งŒ์•ฝ ๊ฐ•์ œ์ ์œผ๋กœ ์ข…๋ฃŒ๊ฐ€ ๋˜์—ˆ์„ ๊ฒฝ์šฐ ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•œ signal handler๋‹ค. ํƒ€ ์“ฐ๋ ˆ๋“œ์—์„œ ๊ณตํ†ต์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ์ž์›์ธ CLIENTS, SENDER ์ „์—ญ๋ณ€์ˆ˜์˜ ์‚ฌ์šฉ์ด ์กด์žฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— mutex lock์„ ์ง„ํ–‰ํ•˜์—ฌ race condition์„ ์˜ˆ๋ฐฉํ•˜์˜€๊ณ , lock์ด ๊ฑธ๋ฆฐ ์ดํ›„์—๋Š” ๋ชจ๋“  ์—ด๋ฆฐ CLIENT socket์„ ๋‹ซ๊ณ  ํž™์— ์ €์žฅ๋œ ์ด๋ฆ„๊ฐ’์„ ํ•ด์ œํ•œ ๋’ค mutex unlock์„ ์ง„ํ–‰ํ•˜๋ฉฐ, ์ตœ์ข…์ ์œผ๋กœ ์ด์šฉ ์ข…๋ฃŒ ๋ฌธ๊ตฌ ์ถœ๋ ฅ ํ›„ exitํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ๋ฐ”์ด๋„ˆ๋ฆฌ๊ฐ€ ์ข…๋ฃŒ๋œ๋‹ค.

์ดํ•˜์— ์กด์žฌํ•˜๋Š” pthread_mutex_lock ๋ฐ unlock ํ•จ์ˆ˜์˜ ์‚ฌ์šฉ์€ ๋ชจ๋‘ critical section์— ์ ‘๊ทผ์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋ผ๋Š” ๊ฐ™์€ ๋ชฉ์ ์„ ์œ„ํ•ด ์กด์žฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์„ค๋ช…์„ ์ƒ๋žตํ•˜๊ฒ ๋‹ค. ๋˜ํ•œ, mutex lock ๋ฐ unlock์€ ์•„๋ฌด ๊ณณ์—์„œ๋‚˜ ๋‚จ์šฉํ•˜์ง€ ์•Š์•˜๋‹ค.

main

s_main ๊ตฌํ˜„๋œ ํ•จ์ˆ˜๋“ค(์ดํ•˜ ์„ค๋ช…)์„ ํ†ตํ•ด ๊ตฌํ˜„๋๋‹ค. ๋จผ์ €, ์ถ”ํ›„์— ๋ฌดํ•œ ๋ฐ˜๋ณต์„ ์ง„ํ–‰ํ•  ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์—, ๊ฐ•์ œ์ข…๋ฃŒ๋ฅผ ํ†ตํ•œ Interrupt์ด๋‚˜ abort๊ฐ€ ๋ฐœ์ƒํ•  ๊ฒฝ์šฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ signal ์ฒ˜๋ฆฌ๋ฅผ ์„ ์–ธํ–ˆ๋‹ค. ๋˜, recvRuntine๊ณผ sendRutine์„ ์ž‘๋™ํ•  ์“ฐ๋ ˆ๋“œ๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•œ ์“ฐ๋ ˆ๋“œ ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•œ๋‹ค. recvRutine ๊ฒฝ์šฐ ๊ฐ (์ตœ๋Œ€ 5๊ฐœ์˜)์†Œ์ผ“ ๋„คํŠธ์›Œํฌ๋งˆ๋‹ค ๋ชจ๋‘์˜ ์ž…๋ ฅ์„ ๋ฐ›์•„์™€์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์“ฐ๋ ˆ๋“œ ์‚ฌ์ด์ฆˆ 5์˜ ๋ฐฐ์—ด์„ ์„ ์–ธํ–ˆ๋‹ค. ๊ทธ ์ดํ›„์— ์ธ์ž๋ฅผ ํ†ตํ•ด port๋ฅผ ๋ฐ›์•„์˜ค๊ณ , sendRoutine์„ ์‹คํ–‰ํ•˜๋Š” ์“ฐ๋ ˆ๋“œ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

์ดํ›„ ๋ฌดํ•œ๋ฐ˜๋ณต ๋ฃจํ”„๋ฅผ ํ†ตํ•ด ๋ฐ›์•„์˜จ port๋ฅผ ํ†ตํ•ด socket์„ ํ˜•์„ฑ ๋ฐ ์—ฐ๊ฒฐ์„ ์ˆ˜์šฉํ•˜๊ณ  client์ •๋ณด๋ฅผ ์ „์—ญ๋ณ€์ˆ˜์— ์ €์žฅํ•˜๋ฉฐ, ๊ฐ client ์†Œ์ผ“๋งˆ๋‹ค recvRoutine ์“ฐ๋ ˆ๋“œ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. ์ด ๊ณผ์ •์€ ๊ฐ•์ œ๋กœ ์ข…๋ฃŒํ•˜๊ธฐ ์ „๊นŒ์ง€ ๋ฌดํ•œ ๋ฐ˜๋ณต๋œ๋‹ค.

void *sendRoutine(void *a)

s_sendRoutine

๋ฌดํ•œ ๋ฃจํ”„๋ฅผ ๋„๋Š” ์“ฐ๋ ˆ๋“œ ๋ฃจํ‹ด์ธ๋ฐ, ๋งŒ์•ฝ SENDER์˜ used๋ฉค๋ฒ„ ๋ณ€์ˆ˜๊ฐ€ set ๋˜์–ด์žˆ๋‹ค๋ฉด, ์•ž์„œ ์„ค๋ช…ํ•œ sendMsgํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด SENDER๋ฅผ ์ œ์™ธํ•œ ๋ชจ๋“  ์—ด๋ฆฐ socket์—๊ฒŒ SENDER์˜ buffer๋ฅผ ์ „์†กํ•œ๋‹ค. ๋‹ค๋งŒ ๋งŒ์•ฝ SENDER ์†Œ์ผ“์˜ DISCONNECT๋ฅผ ์•Œ๋ฆฌ๋Š” ๊ฒฝ์šฐ์—๋Š” ๋‚ด๋ถ€ ์ „์†ก ๊ณผ์ •๋งŒ ์กฐ๊ธˆ ๋‹ค๋ฅด๋‹ค. ์ดํ›„์— ๋ชจ๋“  ์ „์†ก์ด ๋๋‚ฌ๋‹ค๋ฉด server์—๊ฒŒ๋„ printf๋กœ ๋˜‘๊ฐ™์€ ๋ฉ”์‹œ์ง€๋ฅผ ์ถœ๋ ฅํ•˜๋ฉฐ, ์‚ฌ์šฉ๋œ buffer๋ฅผ ๋ชจ๋‘ free์‹œํ‚ค๊ณ  pointer๋Š” NULL๋กœ ๊ฐ’์„ ์žฌํ• ๋‹นํ•œ๋‹ค.

void *recvRoutine(void *arg)

s_recvRoutine

5๊ฐœ์˜ ์“ฐ๋ ˆ๋“œ๊ฐ€ ๋™์‹œ์— ๋ฌดํ•œ ๋ฃจํ”„๋ฅผ ๋„๋Š” ๋ฃจํ‹ด์ธ๋ฐ, ๋งŒ์•ฝ ํ•œ socket์ด๋ผ๋„ recvMsgํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด message๋ฅผ ๋ฐ›์•„์™”๋‹ค๋ฉด, ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฃจํ‹ด์„ ์ง„ํ–‰ํ•œ๋‹ค.

๋งŒ์ผ ๋ฐ›์•„์˜จ client์— ์ด๋ฆ„์ด ์กด์žฌํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด,

  • ๋ฐ›์•„์˜จ ๋ฉ”์‹œ์ง€๋ฅผ strdup๋ฅผ ํ†ตํ•ด ์ƒˆ๋กœ ํž™์— ํ• ๋‹นํ•˜์—ฌ ์ „์—ญ๋ณ€์ˆ˜์— ์ €์žฅํ•˜๊ณ 
  • ํ•ด๋‹น ํด๋ผ์ด์–ธํŠธ์˜ ์—ฐ๊ฒฐ์„ ์„œ๋ฒ„์— ์ถœ๋ ฅํ•œ๋‹ค
  • ์ดํ›„ ์—ด๋ฆฐ ๋ชจ๋“  ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ๋„ ์—ฐ๊ฒฐ ์ˆ˜๋ฆฝ์„ ์•Œ๋ฆฐ๋‹ค.

๋งŒ์•ฝ ์ด๋ฆ„์ด ์ด๋ฏธ ์กด์žฌํ•œ๋‹ค๋ฉด,

  • ๋ฐ›์•„์˜จ ๋ฉ”์‹œ์ง€์— ๋Œ€ํ•œ ๋ชจ๋“  ์ •๋ณด๋ฅผ SENDER์— ํ• ๋‹นํ•˜๊ณ 
  • sendRoutine์ด ์ •์ƒ์ ์œผ๋กœ ๋ชจ๋“  ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ SENDER์˜ ์ •๋ณด๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋„๋ก ์ „์—ญ๋ณ€์ˆ˜ ๊ฐ’์„ setํ•œ๋‹ค.
  • ๋งŒ์•ฝ ์—ฐ๊ฒฐ ์ข…๋ฃŒ๋ฅผ ์•Œ๋ฆฌ๋Š” QUIT ๋ฉ”์‹œ์ง€์ผ ๊ฒฝ์šฐ์—๋Š” ๋ชจ๋“  CLIENT์˜ ์ •๋ณด๋ฅผ ์ฒ˜์Œ์œผ๋กœ ์ดˆ๊ธฐํ™”ํ•˜๋ฉฐ ํ• ๋‹น๋œ ํž™๋„ ํ•ด์ œํ•œ๋‹ค.

๋ชจ๋“  ๋ฃจํ‹ด์ด ์ข…๋ฃŒ๋˜์—ˆ์„ ๊ฒฝ์šฐ ์ž…๋ ฅ๋ฐ›์€ message๋ฅผ ์ข…๋ฃŒํ•˜๊ณ  ๋‹ค์‹œ ์ฒ˜์Œ์œผ๋กœ ๋Œ์•„๊ฐ€ ๋ฃจํ‹ด์„ ์žฌ์‹œ์ž‘ํ•œ๋‹ค.

Client source

include/client.h

clientHdr

client์—์„œ ์‚ฌ์šฉ๋˜๋Š” ํ•จ์ˆ˜๋“ค์„ ๋ฏธ๋ฆฌ ์„ ์–ธํ•ด๋†จ๋‹ค.

include/client.c

int validateArgv(int argc, const char* argv[])

c_validator

์•ž์„œ ์„ค๋ช…ํ•œ server์˜ validator์˜ ๋ชจ๋“  ๋ฃจํ‹ด๊ณผ ๊ฑฐ์˜ ์œ ์‚ฌํ•˜๋‹ค. ์ž์„ธํ•œ ์„ค๋ช…์€ ์ƒ๋žตํ•œ๋‹ค.

const char* getIP(const char* argv[]) && int getPort(const char* argv[])

c_getInfo

๋„˜๊ฒจ๋ฐ›์€ ์ธ์ž๋ฅผ ํ•จ์ˆ˜ ๊ธฐ๋Šฅ์— ์•Œ๋งž๊ฒŒ, ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ๊ตฌํ˜„๋˜์–ด์žˆ๋‹ค.

int connectSocket(const char* ip, int port)

c_connectSocket

๋จผ์ € addr์˜ family๋ฅผ ์„ค์ •ํ•˜๊ณ , inet_pton API๋ฅผ ํ†ตํ•ด addr์— IP ์ฃผ์†Œ๋ฅผ ์‚ฝ์ž…ํ•œ๋‹ค. ์ดํ›„ addr.sin_port ๋ณ€์ˆ˜์— port๊ฐ’์„ htons API๋ฅผ ํ†ตํ•ด big endian์œผ๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ์ €์žฅํ•˜๊ณ , ์†Œ์ผ“ ์ƒ์„ฑ ๋ฐ connect๋ฅผ ์ง„ํ–‰ํ•œ๋‹ค. ์ด ๋•Œ, connect๊ณผ์ •์—์„œ 3-way handshake ๊ณผ์ • ์ค‘ ํ•˜๋‚˜์ธ syn packet ๋ณด๋‚ด๊ธฐ ๋ฐ syn, ackํŒจํ‚ท ์ „์†ก๋ฐ›๊ธฐ, ackํŒจํ‚ท ์žฌ์ „์†ก์ด ๋ชจ๋‘ ์ด๋ค„์ง„๋‹ค. ์„ฑ๊ณต์ ์œผ๋กœ socket ์ƒ์„ฑ ๋ฐ ์—ฐ๊ฒฐ์ด ์ง„ํ–‰๋๋‹ค๋ฉด socket fd๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

src/client.c

handlers

c_hdlrs

๋ชจ๋“  ์“ฐ๋ ˆ๋“œ์—์„œ ์‚ฌ์šฉ๋  socket์˜ FD์™€, loop ๋™์ž‘์˜ ์—ฌ๋ถ€๋ฅผ ํŒ๋‹จํ•˜๋Š” L, ๊ทธ๋ฆฌ๊ณ  client์˜ ์ด๋ฆ„์„ ์ €์žฅํ•˜๋Š” NICKNAME ์ „์—ญ๋ณ€์ˆ˜ ์„ธ ๊ฐœ๊ฐ€ ์„ ์–ธ๋˜์–ด์žˆ๋‹ค. ๊ทธ ๋ฐ‘์—๋Š” ๊ฐ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ์„ ์–ธ๋˜์–ด์žˆ๋Š”๋ฐ, abort์˜ ๊ฒฝ์šฐ ์—ฐ๊ฒฐ ์ˆ˜๋ฆฝ ์‹คํŒจ์ด๋ฏ€๋กœ ์—ฐ๊ฒฐ ์‹คํŒจ์— ๋Œ€ํ•œ ์•Œ๋ฆผ์„ ์ถœ๋ ฅํ•˜๊ณ , interrupt์˜ ๊ฒฝ์šฐ ๊ฐ•์ œ์ข…๋ฃŒ์ด๋ฏ€๋กœ, ๋ชจ๋“  ์ข…๋ฃŒ ๋ฃจํ‹ด์„ ๋”ฐ๋ฅผ ์ˆ˜ ์žˆ๋„๋ก handlingํ•œ ์ดํ›„ ๋ฐ”์ด๋„ˆ๋ฆฌ๊ฐ€ ์ข…๋ฃŒ๋œ๋‹ค.

void *sendRoutine(void *a)

c_sendRoutine

L ๋ณ€์ˆ˜๋กœ ์ข…๋ฃŒ ์—ฌ๋ถ€๋ฅผ ํŒ๋‹จํ•˜์—ฌ L ๋ณ€์ˆ˜๊ฐ€ unset ๋  ๋•Œ๊นŒ์ง€ ๋ฌดํ•œ ๋ฃจํ”„๋ฅผ ๋Œ๊ณ , readBufํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด message๋ฅผ ์ž…๋ ฅ๋ฐ›๋Š”๋‹ค. ์ž…๋ ฅ๋ฐ›์€ message๋ฅผ ์„œ๋ฒ„ ์†Œ์ผ“์— ์ „์†กํ•œ๋‹ค. ๋งŒ์ผ ์ž…๋ ฅ๋ฐ›์€ message๊ฐ€ ์ข…๋ฃŒ๋ฅผ ์˜๋ฏธํ•˜๋Š” QUIT์ผ ๊ฒฝ์šฐ, ๋ฉ”์‹œ์ง€๋ฅผ ์ถœ๋ ฅํ•œ ๋’ค L ๋ณ€์ˆ˜๋ฅผ 0์œผ๋กœ setํ•˜์—ฌ, ์„œ๋ฒ„์™€ ์—ฐ๊ฒฐ ์ข…๋ฃŒ ๋ฐ ๋ฐ”์ด๋„ˆ๋ฆฌ ์ข…๋ฃŒ๋ฅผ ์ง„ํ–‰ํ•œ๋‹ค.

void *recvRoutine(void *a)

c_recvRoutine

L ๋ณ€์ˆ˜๋กœ ์ข…๋ฃŒ ์—ฌ๋ถ€๋ฅผ ํŒ๋‹จํ•˜์—ฌ L ๋ณ€์ˆ˜๊ฐ€ unset ๋  ๋•Œ๊นŒ์ง€ ๋ฌดํ•œ ๋ฃจํ”„๋ฅผ ๋Œ๋ฉฐ recvMsg ํ•จ์ˆ˜๋ฅผ ์ง„ํ–‰ํ•œ๋‹ค. recvMsg ํ•จ์ˆ˜๋กœ ๋ฐ›์•„์˜จ message๋ฅผ ๋‹จ์ˆœํžˆ ์ถœ๋ ฅํ•˜๋Š” ๊ฒƒ์ด ์ „๋ถ€๋‹ค.

int main(int argc, const char* argv[])

c_main setupํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ file stream์„ ์ •๋ฆฌํ•˜๊ณ , signal ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ABORT์™€ INTERRUPT๋ฅผ ํ•ธ๋“ค๋งํ•œ๋‹ค. ์ดํ›„ ์ธ์ž๋ฅผ ํ†ตํ•ด ip, port๋ฅผ getํ•˜๊ณ , ๋„˜๊ฒจ๋ฐ›์€ NICKNAME์„ ํž™์œผ๋กœ ์žฌํ• ๋‹นํ•˜์—ฌ ์ „์—ญ๋ณ€์ˆ˜์— ์ €์žฅํ•œ๋‹ค. ์ดํ›„์— NICKNAME์„ ์„œ๋ฒ„์—๊ฒŒ ์ „์†กํ•˜๊ณ , ์—ฐ๊ฒฐ ์ˆ˜๋ฆฝ์„ ์Šค์Šค๋กœ ์ถœ๋ ฅํ•œ ๋’ค L ์ „์—ญ๋ณ€์ˆ˜๋ฅผ setํ•˜๊ณ  ์ด์ „์— ์„ค๋ช…ํ•œ ์“ฐ๋ ˆ๋“œ๋ฅผ ๊ฐ๊ฐ ์‹คํ–‰์‹œํ‚จ๋‹ค. ์ดํ›„์— join์„ ํ†ตํ•ด sendThread์˜ ์ข…๋ฃŒ๋ฅผ ๋Œ€๊ธฐํ•˜๋Š”๋ฐ, ์ด๋Š” ์„œ๋ฒ„์™€์˜ ์—ฐ๊ฒฐ์˜ ์ข…๋ฃŒ๋ฅผ ์˜๋ฏธํ•œ๋‹ค. sendThread๊ฐ€ ์—ฐ๊ฒฐ ์ข…๋ฃŒ๋˜์—ˆ๋‹ค๋ฉด, recvThread๋„ ๊ฐ•์ œ๋กœ ์ข…๋ฃŒ์‹œํ‚ค๊ณ , server FD๋‹ซ๊ธฐ ๋ฐ, NICKNAME ํž™ ๊ณต๊ฐ„ ํ•ด์ œ๋ฅผ ์ง„ํ–‰ํ•œ๋‹ค.

Execution

Screenshot dump

execute

connection์ด ์„ฑ๊ณตํ•  ๊ฒฝ์šฐ, (3-way handshake) ์„œ๋ฒ„๋Š” ํด๋ผ์ด์–ธํŠธ์˜ ์ •๋ณด๋ฅผ ์ถœ๋ ฅํ•˜๊ณ  ๋Œ€ํ™”๋ฅผ ์ค‘๊ฐœํ•œ๋‹ค. ๊ฐ ํด๋ผ์ด์–ธํŠธ ์—ญ์‹œ ์ƒˆ๋กœ ์—ฐ๊ฒฐ๋œ ์œ ์ €์˜ ์—ฐ๊ฒฐ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๊ณ , ๊ฐ์ž ์—ฐ๊ฒฐ ์ดํ›„ ๋Œ€ํ™”๋ฅผ ์ง„ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

escape

QUIT๋ฅผ ์ž…๋ ฅํ•˜์ž ์ข…๋ฃŒ๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. ๋˜ ์ด์ „ ์Šคํฌ๋ฆฐ์ƒท์„ ํ™•์ธํ•˜๋ฉด, ์ข…๋ฃŒ ์ •๋ณด ๋˜ํ•œ ๋ชจ๋“  ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„์— ์ถœ๋ ฅ๋จ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

About

Develop the Chat Application multithreaded

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages