├── 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 | }
--------------------------------------------------------------------------------