Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
G
git-task-2
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Janaki Ram Puli
git-task-2
Commits
c3d190f9
You need to sign in or sign up before continuing.
Commit
c3d190f9
authored
Aug 01, 2021
by
guitarhero22
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Only Listens
parent
5a89ede9
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
206 additions
and
0 deletions
+206
-0
README.md
README.md
+4
-0
server.c
server.c
+202
-0
No files found.
README.md
View file @
c3d190f9
# Simple Chat Server
# Simple Chat Server
This is a simple chat server that broadcasts messages to all users.
This is a simple chat server that broadcasts messages to all users.
### References
-
[
Beej's Socket Programming Guide
](
https://beej.us/guide/bgnet/pdf/bgnet_usl_c_1.pdf
)
server.c
0 → 100644
View file @
c3d190f9
/*
** pollserver.c -- a cheezy multiperson chat server
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <poll.h>
#define PORT "9034" // Port we're listening on
// Get sockaddr, IPv4 or IPv6:
void
*
get_in_addr
(
struct
sockaddr
*
sa
)
{
if
(
sa
->
sa_family
==
AF_INET
)
{
return
&
(((
struct
sockaddr_in
*
)
sa
)
->
sin_addr
);
}
return
&
(((
struct
sockaddr_in6
*
)
sa
)
->
sin6_addr
);
}
// Return a listening socket
int
get_listener_socket
(
void
)
{
int
listener
;
// Listening socket descriptor
int
yes
=
1
;
// For setsockopt() SO_REUSEADDR, below
int
rv
;
struct
addrinfo
hints
,
*
ai
,
*
p
;
// Get us a socket and bind it
memset
(
&
hints
,
0
,
sizeof
hints
);
hints
.
ai_family
=
AF_UNSPEC
;
hints
.
ai_socktype
=
SOCK_STREAM
;
hints
.
ai_flags
=
AI_PASSIVE
;
if
((
rv
=
getaddrinfo
(
NULL
,
PORT
,
&
hints
,
&
ai
))
!=
0
)
{
fprintf
(
stderr
,
"selectserver: %s
\n
"
,
gai_strerror
(
rv
));
exit
(
1
);
}
for
(
p
=
ai
;
p
!=
NULL
;
p
=
p
->
ai_next
)
{
listener
=
socket
(
p
->
ai_family
,
p
->
ai_socktype
,
p
->
ai_protocol
);
if
(
listener
<
0
)
{
continue
;
}
// Lose the pesky "address already in use" error message
setsockopt
(
listener
,
SOL_SOCKET
,
SO_REUSEADDR
,
&
yes
,
sizeof
(
int
));
if
(
bind
(
listener
,
p
->
ai_addr
,
p
->
ai_addrlen
)
<
0
)
{
close
(
listener
);
continue
;
}
break
;
}
freeaddrinfo
(
ai
);
// All done with this
// If we got here, it means we didn't get bound
if
(
p
==
NULL
)
{
return
-
1
;
}
// Listen
if
(
listen
(
listener
,
10
)
==
-
1
)
{
return
-
1
;
}
return
listener
;
}
// Add a new file descriptor to the set
void
add_to_pfds
(
struct
pollfd
*
pfds
[],
int
newfd
,
int
*
fd_count
,
int
*
fd_size
)
{
// If we don't have room, add more space in the pfds array
if
(
*
fd_count
==
*
fd_size
)
{
*
fd_size
*=
2
;
// Double it
*
pfds
=
realloc
(
*
pfds
,
sizeof
(
**
pfds
)
*
(
*
fd_size
));
}
(
*
pfds
)[
*
fd_count
].
fd
=
newfd
;
(
*
pfds
)[
*
fd_count
].
events
=
POLLIN
;
// Check ready-to-read
(
*
fd_count
)
++
;
}
// Remove an index from the set
void
del_from_pfds
(
struct
pollfd
pfds
[],
int
i
,
int
*
fd_count
)
{
// Copy the one from the end over this one
pfds
[
i
]
=
pfds
[
*
fd_count
-
1
];
(
*
fd_count
)
--
;
}
// Main
int
main
(
void
)
{
int
listener
;
// Listening socket descriptor
int
newfd
;
// Newly accept()ed socket descriptor
struct
sockaddr_storage
remoteaddr
;
// Client address
socklen_t
addrlen
;
char
buf
[
256
];
// Buffer for client data
char
remoteIP
[
INET6_ADDRSTRLEN
];
// Start off with room for 5 connections
// (We'll realloc as necessary)
int
fd_count
=
0
;
int
fd_size
=
5
;
struct
pollfd
*
pfds
=
malloc
(
sizeof
*
pfds
*
fd_size
);
// Set up and get a listening socket
listener
=
get_listener_socket
();
if
(
listener
==
-
1
)
{
fprintf
(
stderr
,
"error getting listening socket
\n
"
);
exit
(
1
);
}
// Add the listener to set
pfds
[
0
].
fd
=
listener
;
pfds
[
0
].
events
=
POLLIN
;
// Report ready to read on incoming connection
fd_count
=
1
;
// For the listener
// Main loop
for
(;;)
{
int
poll_count
=
poll
(
pfds
,
fd_count
,
-
1
);
if
(
poll_count
==
-
1
)
{
perror
(
"poll"
);
exit
(
1
);
}
// Run through the existing connections looking for data to read
for
(
int
i
=
0
;
i
<
fd_count
;
i
++
)
{
// Check if someone's ready to read
if
(
pfds
[
i
].
revents
&
POLLIN
)
{
// We got one!!
if
(
pfds
[
i
].
fd
==
listener
)
{
// If listener is ready to read, handle new connection
addrlen
=
sizeof
remoteaddr
;
newfd
=
accept
(
listener
,
(
struct
sockaddr
*
)
&
remoteaddr
,
&
addrlen
);
if
(
newfd
==
-
1
)
{
perror
(
"accept"
);
}
else
{
add_to_pfds
(
&
pfds
,
newfd
,
&
fd_count
,
&
fd_size
);
printf
(
"pollserver: new connection from %s on "
"socket %d
\n
"
,
inet_ntop
(
remoteaddr
.
ss_family
,
get_in_addr
((
struct
sockaddr
*
)
&
remoteaddr
),
remoteIP
,
INET6_ADDRSTRLEN
),
newfd
);
}
}
else
{
// If not the listener, we're just a regular client
int
nbytes
=
recv
(
pfds
[
i
].
fd
,
buf
,
sizeof
buf
,
0
);
int
sender_fd
=
pfds
[
i
].
fd
;
if
(
nbytes
<=
0
)
{
// Got error or connection closed by client
if
(
nbytes
==
0
)
{
// Connection closed
printf
(
"pollserver: socket %d hung up
\n
"
,
sender_fd
);
}
else
{
perror
(
"recv"
);
}
close
(
pfds
[
i
].
fd
);
// Bye!
del_from_pfds
(
pfds
,
i
,
&
fd_count
);
}
else
{
// We got some good data from a client
}
}
// END handle data from client
}
// END got ready-to-read from poll()
}
// END looping through file descriptors
}
// END for(;;)--and you thought it would never end!
return
0
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment