Advertisement
Guest User

Untitled

a guest
Jan 21st, 2020
75
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.34 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <sys/types.h>
  3. #include <sys/socket.h>
  4. #include <netinet/in.h>
  5. #include <netdb.h>
  6. #include <stdlib.h>
  7. #include <arpa/inet.h>
  8. #include <unistd.h>
  9. #include <string.h>
  10. #include <sys/wait.h>
  11. #include <signal.h>
  12.  
  13.  
  14. #define BUFF_SIZE 256
  15.  
  16. /* struktura do przechowywania nazw uzytkownikow i przesylania wiadomosci */
  17. struct my_msg
  18. {
  19. char name[16];
  20. char text[BUFF_SIZE];
  21. };
  22.  
  23.  
  24. int main(int argc, char *argv[])
  25. {
  26. int s;
  27. int sockfd;
  28. struct sockaddr_in server, client, *temp;
  29. struct addrinfo *res;
  30. struct my_msg msg, msg1;
  31. socklen_t addrlen;
  32. pid_t potomek;
  33.  
  34.  
  35. if( argc < 2 || argc > 3)
  36. {
  37. printf("Zla ilosc argumentow. Pattern: ./nazwaprogramu IP nazwauzytkownika(opcjonalnie)");
  38. return 1;
  39. }
  40.  
  41. /* gdy nazwa niepodana przypisanie domyslnej "NN" */
  42. if( argc == 2 )
  43. {
  44. strcpy(msg.name, "NN");
  45. }
  46.  
  47. /* gdy nazwa podana przypisanie wybranej przez uzytkownika */
  48. if( argc == 3 )
  49. {
  50. if( strlen(argv[2]) > 16 )
  51. {
  52. printf("Zbyt dluga nazwa uzytkownika. Skracam nazwe do 16 znakow \n");
  53. strncpy(msg.name, argv[2], 16); /* jesli nazwa jest za dluga, skracamy ja do 16 znakow */
  54. }
  55. else /* przypisanie nazwy bez zastrzezen */
  56. {
  57. strcpy(msg.name, argv[2]);
  58. }
  59. }
  60.  
  61. /* tworzymy strukture adresowa gniazda */
  62. s = getaddrinfo(argv[1], "7777", NULL, &res);
  63. if( s != 0)
  64. {
  65. printf("getaddrinfo: %s\n", gai_strerror(s)); /* gdy niepowiodlo sie wyswietlamy komunikat bledu i wymuszamy koniec programu */
  66. return 1;
  67. }
  68.  
  69.  
  70. temp = (struct sockaddr_in *)(res->ai_addr);
  71.  
  72. /* getaddrinfo zwraca do res liste struktur adresow */
  73.  
  74. server.sin_family = AF_INET; /* ustawia typ IP jako IPv4 */
  75. server.sin_port = htons(7777); /* ustawia port serwera */
  76. server.sin_addr.s_addr = htonl(INADDR_ANY); /* ustawia adres uniwersalnie dla każdego interfaceu */
  77.  
  78. client.sin_family = AF_INET; /* ustawia typ IP jako IPv4 */
  79. client.sin_port = htons(7777); /* ustawia port z którego będzie korzystać podczas komunikacji */
  80. client.sin_addr = temp->sin_addr; /* ustawia docelowe IP */
  81.  
  82. addrlen = sizeof(client); /* zmienna dlugosci adresu dla wezwania recvfrom */
  83.  
  84.  
  85. /* int socket(int domain, int type, int protocol); tworzy punkt końcowy w komunikacji, zwraca deskryptor pliku*/
  86. /* AF_INET protokół IPv4 */
  87. /* SOCK_DGRAM Wspiera datagramy (bezpołączeniowy, niepraktyczny, musi miec wiadomosci ustalonej dlugosci). */
  88. /* protokół równy 0 gdyż nie chcemy go specyfikować */
  89. if( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
  90. {
  91. printf("Blad tworzenia gniazda \n");
  92. return 1;
  93. }
  94.  
  95.  
  96. /* int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); */
  97. /* przypisywanie adresu do gniazda przekazywane przez deskryptor sockfd */
  98. if( bind(sockfd, (struct sockaddr*)&server, sizeof(server)) < 0)
  99. {
  100. printf("Blad bindowania \n");
  101. close(sockfd);
  102. return 1;
  103. }
  104.  
  105. /* void freeaddrinfo(struct addrinfo *res); */
  106. /* funkcja uwalnia pamięć alokowaną dla dynamicznie alokowanej zmiennej res. */
  107. freeaddrinfo(res);
  108.  
  109. printf("Rozpoczynam czat z %s. Napisz <koniec> by zakonczyc czat.\n", inet_ntoa(client.sin_addr));
  110. strcpy(msg.text, "<poczatek>");
  111. if(sendto(sockfd, &msg, sizeof(msg), 0,(struct sockaddr *)&client, sizeof(client)) < 0)
  112. {
  113. printf("Blad wysylania informacji o dolaczeniu\n");
  114. close(sockfd);
  115. return 1;
  116. }
  117.  
  118. /* Tworzę potomka odpowiedającego za wyświetlanie wiadomości */
  119. if((potomek = fork()) == 0)
  120. {
  121. while(1)
  122. {
  123. /* obsluga bledu pobierania wiadomosci */
  124. if(recvfrom(sockfd, &msg1, sizeof(msg1), 0, (struct sockaddr *)&client, &addrlen) < 0)
  125. {
  126. printf("Blad przy pobieraniu wiadomosci\n");
  127. return 1;
  128. }
  129.  
  130. /* informacja o dolaczeniu uzytkownika do czatu */
  131. if(strcmp(msg1.text,"<poczatek>") == 0)
  132. {
  133. printf("\n[%s (%s) dolaczyl do rozmowy]\n", msg1.name, inet_ntoa(client.sin_addr));
  134. }
  135. /* informacja o zakonczeniu rozmowy przez uzytkownika */
  136. else if (strcmp(msg1.text,"<koniec>") == 0)
  137. {
  138. printf("\n[%s (%s) zakonczyl rozmowe]\n", msg1.name, inet_ntoa(client.sin_addr));
  139. }
  140. /* wypisywanie wiadomosci */
  141. else
  142. {
  143. printf("\n[%s (%s)]: %s\n", msg1.name, inet_ntoa(client.sin_addr), msg1.text);
  144. }
  145. printf("[%s]> ", msg.name);
  146. /* fflush(stdout) celem jest wyczyszczenie bufora wyjściowego i przeniesienie danych z niego na konsolę */
  147. /* nie tracimy w ten sposob tworzonej wiadomosci podczas odbierania innej */
  148. fflush(stdout);
  149. }
  150. /* sprzatanie po programie */
  151. close(sockfd);
  152. exit(0);
  153. }
  154. else
  155. {
  156. /* proces rodzica odpowiedzialny za wysyłanie wiadomości */
  157. while(1)
  158. {
  159.  
  160. printf("[%s]> ", msg.name);
  161. fgets(msg.text, BUFF_SIZE, stdin);
  162. msg.text[strlen(msg.text)-1] = '\0';
  163. /* wysylanie wiadomosci nie powiodlo sie */
  164. if(sendto(sockfd, &msg, sizeof(msg), 0,(struct sockaddr *)&client, (sizeof(client))) < 0)
  165. {
  166. printf("Blad przy wysylaniu wiadomosci\n");
  167. close(sockfd);
  168. return 1;
  169. }
  170. /* konczymy uzytkowanie czatu, zabijamy proces potomny, zamykamy deskryptor */
  171. if(strcmp(msg.text,"<koniec>") == 0)
  172. {
  173. kill(potomek, SIGINT);
  174. close(sockfd);
  175. return 0;
  176. }
  177. }
  178.  
  179. }
  180.  
  181. return 0;
  182. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement