Програмирање утичнице је начин повезивања два чвора на мрежи ради међусобног комуницирања. Једна утичница (чвор) слуша на одређеном порту на ИП-у, док друга утичница допире до друге да би успоставила везу. Сервер формира утичницу слушаоца док клијент посеже до сервера.
Програмирање утичнице се широко користи у апликацијама за размену тренутних порука, бинарном стримовању и сарадњи докумената на платформама за стриминг на мрежи итд.
Пример
У овом Ц програму размењујемо једну здраву поруку између сервера и клијента да бисмо демонстрирали модел клијент/сервер.
сервер.ц
C#include #include #include #include #include #include #define PORT 8080 int main(int argc char const* argv[]) { int server_fd new_socket; ssize_t valread; struct sockaddr_in address; int opt = 1; socklen_t addrlen = sizeof(address); char buffer[1024] = { 0 }; char* hello = 'Hello from server'; // Creating socket file descriptor if ((server_fd = socket(AF_INET SOCK_STREAM 0)) < 0) { perror('socket failed'); exit(EXIT_FAILURE); } // Forcefully attaching socket to the port 8080 if (setsockopt(server_fd SOL_SOCKET SO_REUSEADDR | SO_REUSEPORT &opt sizeof(opt))) { perror('setsockopt'); exit(EXIT_FAILURE); } address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; address.sin_port = htons(PORT); // Forcefully attaching socket to the port 8080 if (bind(server_fd (struct sockaddr*)&address sizeof(address)) < 0) { perror('bind failed'); exit(EXIT_FAILURE); } if (listen(server_fd 3) < 0) { perror('listen'); exit(EXIT_FAILURE); } if ((new_socket = accept(server_fd (struct sockaddr*)&address &addrlen)) < 0) { perror('accept'); exit(EXIT_FAILURE); } // subtract 1 for the null // terminator at the end valread = read(new_socket buffer 1024 - 1); printf('%sn' buffer); send(new_socket hello strlen(hello) 0); printf('Hello message sentn'); // closing the connected socket close(new_socket); // closing the listening socket close(server_fd); return 0; }
клијент.ц
C#include #include #include #include #include #define PORT 8080 int main(int argc char const* argv[]) { int status valread client_fd; struct sockaddr_in serv_addr; char* hello = 'Hello from client'; char buffer[1024] = { 0 }; if ((client_fd = socket(AF_INET SOCK_STREAM 0)) < 0) { printf('n Socket creation error n'); return -1; } serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(PORT); // Convert IPv4 and IPv6 addresses from text to binary // form if (inet_pton(AF_INET '127.0.0.1' &serv_addr.sin_addr) <= 0) { printf( 'nInvalid address/ Address not supported n'); return -1; } if ((status = connect(client_fd (struct sockaddr*)&serv_addr sizeof(serv_addr))) < 0) { printf('nConnection Failed n'); return -1; } // subtract 1 for the null // terminator at the end send(client_fd hello strlen(hello) 0); printf('Hello message sentn'); valread = read(client_fd buffer 1024 - 1); printf('%sn' buffer); // closing the connected socket close(client_fd); return 0; }
Састављање
gcc client.c -o clientgcc server.c -o server
Излаз
Client:Hello message sentHello from serverServer:Hello from clientHello message sentКомпоненте програмирања соцкета
1. Утичнице
Утичнице су једна од основних компоненти које програм користи за приступ мрежи ради комуникације са другим процесима/чворовима преко мреже. То је једноставно комбинација ИП адресе и броја порта који делује као крајња тачка за комуникацију.
Пример: 192.168.1.1:8080 где два дела одвојена двоточком представљају ИП адреса ( 192.168.1.1 ) анд тхе број порта ( 8080 ).
Типови утичница:
- ТЦП утичница (Стреам Соцкет): Пружа поуздану комуникацију засновану на вези (тј. ТЦП протокол ).
- УДП утичница (датаграмска утичница): Омогућава бржу комуникацију без везе, али непоуздану (тј. УДП протокол ).
2. Модел клијент-сервер
Тхе клијент-сервер модел односи се на архитектуру која се користи у програмирању сокета где клијент и сервер међусобно комуницирају ради размене информација или услуга. Ова архитектура омогућава клијенту да шаље захтеве за услугу, а серверу да обрађује и шаље одговоре на те захтеве за услугу.
Дијаграм стања за модел сервера и клијента
Дијаграм стања за серверски и клијентски модел СоцкетаПрограмирање утичнице у Ц-у је моћан начин управљања мрежном комуникацијом.
Креирање процеса на страни сервера
Сервер се креира следећим корацима:
како избити из вхиле петље јава
1. Креирање утичнице
Овај корак укључује креирање утичнице помоћу функције соцкет().
Параметри:
- соцкфд: дескриптор утичнице цео број (попут ручице датотеке)
- домен: цео број специфицира комуникациони домен. Користимо АФ_ ЛОЦАЛ како је дефинисано у ПОСИКС стандарду за комуникацију између процеса на истом хосту. За комуникацију између процеса на различитим хостовима повезаним преко ИПВ4 користимо АФ_ИНЕТ и АФ_И НЕТ 6 за процесе повезане преко ИПВ6.
- тип: тип комуникације
СОЦК_СТРЕАМ: ТЦП (оријентисан на поуздану везу)
СОЦК_ДГРАМ: УДП (непоуздано без везе) - протокол: Вредност протокола за Интернет Протоцол(ИП) која је 0. Ово је исти број који се појављује у пољу протокола у ИП заглављу пакета. (ман протоколи за више детаља)
sockfd = socket(domain type protocol)
2. Подесите утичницу опт
Ово помаже у манипулисању опцијама за утичницу на коју упућује дескриптор датотеке соцкфд. Ово је потпуно опционо, али помаже у поновној употреби адресе и порта. Спречава грешке као што су: адреса која се већ користи.
Csetsockopt(sockfd level optname optval socklen_t optlen);
3. Везите
Након креирања утичнице, функција бинд() повезује сокет са адресом и бројем порта наведеним у аддр(прилагођена структура података). У примеру кода везујемо сервер за локални хост, па користимо ИНАДДР_АНИ да наведемо ИП адресу.
C++bind(sockfd sockaddr *addr socklen_t addrlen);
Параметри:
- соцкфд : дескриптор датотеке соцкет креиран помоћу функције соцкет().
- аддр : показивач на структуру соцкаддр која садржи ИП адресу и број порта за повезивање утичнице.
- аддрлен : дужина структуре адресе.
4. Слушајте
У овом кораку сервер користи функцију листен() која поставља утичницу сервера у пасивни режим где чека да се клијент приближи серверу да би успоставио везу. Заостатак дефинише максималну дужину до које може да порасте ред веза на чекању за соцкфд. Ако захтев за повезивање стигне када је ред пун, клијент може добити грешку са индикацијом ЕЦОННРЕФУСЕД.
Clisten(sockfd backlog);
Параметерс :
- соцкфд : дескриптор датотеке соцкет креиран помоћу функције соцкет().
- заостатак : број који представља величину реда који држи везе на чекању док сервер чека да прихвати везу.
5. Прихватите
У овом кораку сервер издваја први захтев за повезивање из реда веза на чекању за утичницу за слушање, соцкфд креира нову повезану утичницу користећи прихвати() функцију и враћа нови дескриптор датотеке који се односи на ту утичницу. У овом тренутку се успоставља веза између клијента и сервера и они су спремни за пренос података.
Cnew_socket= accept(sockfd sockaddr *addr socklen_t *addrlen);
Параметри:
- соцкфд : дескриптор датотеке соцкета који враћају соцкет() и бинд().
- аддр : показивач на структуру соцкаддр која ће садржати ИП адресу клијента и број порта.
- аддрлен : показивач на променљиву која одређује дужину адресне структуре.
6. Пошаљи/прими
У овом кораку сервер може да шаље или прима податке од клијента.
Пошаљи(): да пошаље податке клијенту
Csend(sockfd *buf len flags);
Параметри:
- соцкфд : дескриптор датотеке соцкета који враћа функција соцкет().
- буф : показивач на бафер који садржи податке који се шаљу.
- само : број бајтова података који се шаљу.
- заставе : цео број који специфицира различите опције за начин на који се подаци шаљу обично 0 се користи за подразумевано понашање.
Прими() : да добије податке од клијента.
Crecv( sockfd *buf len flags);
Параметри:
- соцкфд : дескриптор датотеке соцкета који враћа функција соцкет().
- буф : показивач на бафер који садржи податке за чување.
- само : број бајтова података који се шаљу.
- заставе : цео број који специфицира различите опције за начин на који се подаци шаљу обично 0 се користи за подразумевано понашање.
6. Затвори
Након што је размена информација завршена, сервер затвара сокет помоћу функције цлосе() и ослобађа системске ресурсе.
Cclose(fd);
Параметри:
- фд: дескриптор датотеке утичнице.
Креирање процеса на страни клијента
Пратите доле наведене кораке за креирање процеса на страни клијента:
1. Прикључак утичнице
Овај корак укључује креирање утичнице која се ради на исти начин као и креирање сокета сервера
2. Повежите се
Системски позив цоннецт() повезује утичницу на коју се позива дескриптор датотеке соцкфд са адресом коју је навео аддр. Адреса и порт сервера су наведени у адр.
C++connect(sockfd sockaddr *addr socklen_t addrlen);
Параметерс
- соцкфд : дескриптор датотеке соцкета који враћа функција соцкет().
- аддр : показивач на структуру соцкаддр која садржи ИП адресу сервера и број порта.
- аддрлен : величина адр.
3. Пошаљи/прими
У овом кораку клијент може да шаље или прима податке са сервера, што се ради помоћу функција сенд() и рециеве() слично као што сервер шаље/прима податке од клијента.
4. Затвори
Када се размена информација заврши, клијент такође треба да затвори креирану утичницу и ослободи системске ресурсе користећи цлосе() функцију на исти начин као и сервер.
Уобичајени проблеми и њихови поправци у програмирању сокета
- Грешке везе: Да бисмо избегли грешке у вези, требало би да обезбедимо да клијент покушава да се повеже са исправним ИП адреса и порт .
- Грешке при повезивању порта: Ове грешке се јављају када је порт већ у употреби од стране друге апликације у овом сценарију, повезивање за тај порт неће успети. Покушајте да користите други порт или затворите претходну апликацију помоћу порта.
- Блокирајуће утичнице: Подразумевано, утичнице су блокиране. То значи да ће позиви као што су аццепт() или рецв() чекати бесконачно ако нема клијентске везе или података. Ако је потребно, можете подесити утичницу у режим без блокирања.