Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <netdb.h>
- #include <stdlib.h>
- #include <arpa/inet.h>
- #include <unistd.h>
- #include <string.h>
- #include <sys/wait.h>
- #include <signal.h>
- #define BUFF_SIZE 256
- /* struktura do przechowywania nazw uzytkownikow i przesylania wiadomosci */
- struct my_msg
- {
- char name[16];
- char text[BUFF_SIZE];
- };
- int main(int argc, char *argv[])
- {
- int s;
- int sockfd;
- struct sockaddr_in server, client, *temp;
- struct addrinfo *res;
- struct my_msg msg, msg1;
- socklen_t addrlen;
- pid_t potomek;
- if( argc < 2 || argc > 3)
- {
- printf("Zla ilosc argumentow. Pattern: ./nazwaprogramu IP nazwauzytkownika(opcjonalnie)");
- return 1;
- }
- /* gdy nazwa niepodana przypisanie domyslnej "NN" */
- if( argc == 2 )
- {
- strcpy(msg.name, "NN");
- }
- /* gdy nazwa podana przypisanie wybranej przez uzytkownika */
- if( argc == 3 )
- {
- if( strlen(argv[2]) > 16 )
- {
- printf("Zbyt dluga nazwa uzytkownika. Skracam nazwe do 16 znakow \n");
- strncpy(msg.name, argv[2], 16); /* jesli nazwa jest za dluga, skracamy ja do 16 znakow */
- }
- else /* przypisanie nazwy bez zastrzezen */
- {
- strcpy(msg.name, argv[2]);
- }
- }
- /* tworzymy strukture adresowa gniazda */
- s = getaddrinfo(argv[1], "7777", NULL, &res);
- if( s != 0)
- {
- printf("getaddrinfo: %s\n", gai_strerror(s)); /* gdy niepowiodlo sie wyswietlamy komunikat bledu i wymuszamy koniec programu */
- return 1;
- }
- temp = (struct sockaddr_in *)(res->ai_addr);
- /* getaddrinfo zwraca do res liste struktur adresow */
- server.sin_family = AF_INET; /* ustawia typ IP jako IPv4 */
- server.sin_port = htons(7777); /* ustawia port serwera */
- server.sin_addr.s_addr = htonl(INADDR_ANY); /* ustawia adres uniwersalnie dla każdego interfaceu */
- client.sin_family = AF_INET; /* ustawia typ IP jako IPv4 */
- client.sin_port = htons(7777); /* ustawia port z którego będzie korzystać podczas komunikacji */
- client.sin_addr = temp->sin_addr; /* ustawia docelowe IP */
- addrlen = sizeof(client); /* zmienna dlugosci adresu dla wezwania recvfrom */
- /* int socket(int domain, int type, int protocol); tworzy punkt końcowy w komunikacji, zwraca deskryptor pliku*/
- /* AF_INET protokół IPv4 */
- /* SOCK_DGRAM Wspiera datagramy (bezpołączeniowy, niepraktyczny, musi miec wiadomosci ustalonej dlugosci). */
- /* protokół równy 0 gdyż nie chcemy go specyfikować */
- if( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
- {
- printf("Blad tworzenia gniazda \n");
- return 1;
- }
- /* int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); */
- /* przypisywanie adresu do gniazda przekazywane przez deskryptor sockfd */
- if( bind(sockfd, (struct sockaddr*)&server, sizeof(server)) < 0)
- {
- printf("Blad bindowania \n");
- close(sockfd);
- return 1;
- }
- /* void freeaddrinfo(struct addrinfo *res); */
- /* funkcja uwalnia pamięć alokowaną dla dynamicznie alokowanej zmiennej res. */
- freeaddrinfo(res);
- printf("Rozpoczynam czat z %s. Napisz <koniec> by zakonczyc czat.\n", inet_ntoa(client.sin_addr));
- strcpy(msg.text, "<poczatek>");
- if(sendto(sockfd, &msg, sizeof(msg), 0,(struct sockaddr *)&client, sizeof(client)) < 0)
- {
- printf("Blad wysylania informacji o dolaczeniu\n");
- close(sockfd);
- return 1;
- }
- /* Tworzę potomka odpowiedającego za wyświetlanie wiadomości */
- if((potomek = fork()) == 0)
- {
- while(1)
- {
- /* obsluga bledu pobierania wiadomosci */
- if(recvfrom(sockfd, &msg1, sizeof(msg1), 0, (struct sockaddr *)&client, &addrlen) < 0)
- {
- printf("Blad przy pobieraniu wiadomosci\n");
- return 1;
- }
- /* informacja o dolaczeniu uzytkownika do czatu */
- if(strcmp(msg1.text,"<poczatek>") == 0)
- {
- printf("\n[%s (%s) dolaczyl do rozmowy]\n", msg1.name, inet_ntoa(client.sin_addr));
- }
- /* informacja o zakonczeniu rozmowy przez uzytkownika */
- else if (strcmp(msg1.text,"<koniec>") == 0)
- {
- printf("\n[%s (%s) zakonczyl rozmowe]\n", msg1.name, inet_ntoa(client.sin_addr));
- }
- /* wypisywanie wiadomosci */
- else
- {
- printf("\n[%s (%s)]: %s\n", msg1.name, inet_ntoa(client.sin_addr), msg1.text);
- }
- printf("[%s]> ", msg.name);
- /* fflush(stdout) celem jest wyczyszczenie bufora wyjściowego i przeniesienie danych z niego na konsolę */
- /* nie tracimy w ten sposob tworzonej wiadomosci podczas odbierania innej */
- fflush(stdout);
- }
- /* sprzatanie po programie */
- close(sockfd);
- exit(0);
- }
- else
- {
- /* proces rodzica odpowiedzialny za wysyłanie wiadomości */
- while(1)
- {
- printf("[%s]> ", msg.name);
- fgets(msg.text, BUFF_SIZE, stdin);
- msg.text[strlen(msg.text)-1] = '\0';
- /* wysylanie wiadomosci nie powiodlo sie */
- if(sendto(sockfd, &msg, sizeof(msg), 0,(struct sockaddr *)&client, (sizeof(client))) < 0)
- {
- printf("Blad przy wysylaniu wiadomosci\n");
- close(sockfd);
- return 1;
- }
- /* konczymy uzytkowanie czatu, zabijamy proces potomny, zamykamy deskryptor */
- if(strcmp(msg.text,"<koniec>") == 0)
- {
- kill(potomek, SIGINT);
- close(sockfd);
- return 0;
- }
- }
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement