├── client-server-flow diagram_peer-to-peer.png ├── README.md └── peer.c /client-server-flow diagram_peer-to-peer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/um4ng-tiw/Peer-to-Peer-Socket-C/HEAD/client-server-flow diagram_peer-to-peer.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Peer to peer program in C 2 | This program involves a peer which can send and receive simultaneously, created using Socket programming in C. Multiple instances of the code can be run in seperate terminal environments to form a peer to peer chat network. 3 | 4 | **Limitations** 5 | 1. The program requires the user to know the port numbers of other users on the same localhost beforehand. 6 | 2. The program is just a demonstration of TCP/IP Socket programming in C. 7 | 8 | **Simultaneous send and receive**
9 | The program achieves simultaneous send and receive by running the receive method on seperate thread. The program involves the use of **select()** system call to identify the ready file descriptors and loop over them to receive the messages in queue. However, this simultaneous send and receive is not refined and may interrupt the user while sending the message. 10 | 11 | **Running instructions**
12 | The program was executed on a Linux system using the gcc compiler. 13 | 14 | ``` 15 | gcc peer.c -o peer1 16 | gcc peer.c -o peer2 17 | ./peer1 18 | ./peer2 19 | ``` 20 | -------------------------------------------------------------------------------- /peer.c: -------------------------------------------------------------------------------- 1 | // C program to demonstrate peer to peer chat using Socket Programming 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | char name[20]; 12 | int PORT; 13 | 14 | void sending(); 15 | void receiving(int server_fd); 16 | void *receive_thread(void *server_fd); 17 | 18 | int main(int argc, char const *argv[]) 19 | { 20 | printf("Enter name:"); 21 | scanf("%s", name); 22 | 23 | printf("Enter your port number:"); 24 | scanf("%d", &PORT); 25 | 26 | int server_fd, new_socket, valread; 27 | struct sockaddr_in address; 28 | int k = 0; 29 | 30 | // Creating socket file descriptor 31 | if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) 32 | { 33 | perror("socket failed"); 34 | exit(EXIT_FAILURE); 35 | } 36 | // Forcefully attaching socket to the port 37 | 38 | address.sin_family = AF_INET; 39 | address.sin_addr.s_addr = INADDR_ANY; 40 | address.sin_port = htons(PORT); 41 | 42 | //Printed the server socket addr and port 43 | printf("IP address is: %s\n", inet_ntoa(address.sin_addr)); 44 | printf("port is: %d\n", (int)ntohs(address.sin_port)); 45 | 46 | if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) 47 | { 48 | perror("bind failed"); 49 | exit(EXIT_FAILURE); 50 | } 51 | if (listen(server_fd, 5) < 0) 52 | { 53 | perror("listen"); 54 | exit(EXIT_FAILURE); 55 | } 56 | int ch; 57 | pthread_t tid; 58 | pthread_create(&tid, NULL, &receive_thread, &server_fd); //Creating thread to keep receiving message in real time 59 | printf("\n*****At any point in time press the following:*****\n1.Send message\n0.Quit\n"); 60 | printf("\nEnter choice:"); 61 | do 62 | { 63 | 64 | scanf("%d", &ch); 65 | switch (ch) 66 | { 67 | case 1: 68 | sending(); 69 | break; 70 | case 0: 71 | printf("\nLeaving\n"); 72 | break; 73 | default: 74 | printf("\nWrong choice\n"); 75 | } 76 | } while (ch); 77 | 78 | close(server_fd); 79 | 80 | return 0; 81 | } 82 | 83 | //Sending messages to port 84 | void sending() 85 | { 86 | 87 | char buffer[2000] = {0}; 88 | //Fetching port number 89 | int PORT_server; 90 | 91 | //IN PEER WE TRUST 92 | printf("Enter the port to send message:"); //Considering each peer will enter different port 93 | scanf("%d", &PORT_server); 94 | 95 | int sock = 0, valread; 96 | struct sockaddr_in serv_addr; 97 | char hello[1024] = {0}; 98 | if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) 99 | { 100 | printf("\n Socket creation error \n"); 101 | return; 102 | } 103 | 104 | serv_addr.sin_family = AF_INET; 105 | serv_addr.sin_addr.s_addr = INADDR_ANY; //INADDR_ANY always gives an IP of 0.0.0.0 106 | serv_addr.sin_port = htons(PORT_server); 107 | 108 | if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) 109 | { 110 | printf("\nConnection Failed \n"); 111 | return; 112 | } 113 | 114 | char dummy; 115 | printf("Enter your message:"); 116 | scanf("%c", &dummy); //The buffer is our enemy 117 | scanf("%[^\n]s", hello); 118 | sprintf(buffer, "%s[PORT:%d] says: %s", name, PORT, hello); 119 | send(sock, buffer, sizeof(buffer), 0); 120 | printf("\nMessage sent\n"); 121 | close(sock); 122 | } 123 | 124 | //Calling receiving every 2 seconds 125 | void *receive_thread(void *server_fd) 126 | { 127 | int s_fd = *((int *)server_fd); 128 | while (1) 129 | { 130 | sleep(2); 131 | receiving(s_fd); 132 | } 133 | } 134 | 135 | //Receiving messages on our port 136 | void receiving(int server_fd) 137 | { 138 | struct sockaddr_in address; 139 | int valread; 140 | char buffer[2000] = {0}; 141 | int addrlen = sizeof(address); 142 | fd_set current_sockets, ready_sockets; 143 | 144 | //Initialize my current set 145 | FD_ZERO(¤t_sockets); 146 | FD_SET(server_fd, ¤t_sockets); 147 | int k = 0; 148 | while (1) 149 | { 150 | k++; 151 | ready_sockets = current_sockets; 152 | 153 | if (select(FD_SETSIZE, &ready_sockets, NULL, NULL, NULL) < 0) 154 | { 155 | perror("Error"); 156 | exit(EXIT_FAILURE); 157 | } 158 | 159 | for (int i = 0; i < FD_SETSIZE; i++) 160 | { 161 | if (FD_ISSET(i, &ready_sockets)) 162 | { 163 | 164 | if (i == server_fd) 165 | { 166 | int client_socket; 167 | 168 | if ((client_socket = accept(server_fd, (struct sockaddr *)&address, 169 | (socklen_t *)&addrlen)) < 0) 170 | { 171 | perror("accept"); 172 | exit(EXIT_FAILURE); 173 | } 174 | FD_SET(client_socket, ¤t_sockets); 175 | } 176 | else 177 | { 178 | valread = recv(i, buffer, sizeof(buffer), 0); 179 | printf("\n%s\n", buffer); 180 | FD_CLR(i, ¤t_sockets); 181 | } 182 | } 183 | } 184 | 185 | if (k == (FD_SETSIZE * 2)) 186 | break; 187 | } 188 | } --------------------------------------------------------------------------------