-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Description
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
int extract_message(char **buf, char **msg)
{
char *newbuf;
int i;
*msg = 0;
if (*buf == 0)
return (0);
i = 0;
while ((*buf)[i])
{
if ((*buf)[i] == '\n')
{
newbuf = calloc(1, sizeof(*newbuf) * (strlen(*buf + i + 1) + 1));
if (newbuf == 0)
return (-1);
strcpy(newbuf, *buf + i + 1);
*msg = *buf;
(*msg)[i + 1] = 0;
*buf = newbuf;
return (1);
}
i++;
}
return (0);
}
char *str_join(char *buf, char *add)
{
char *newbuf;
int len;
if (buf == 0)
len = 0;
else
len = strlen(buf);
newbuf = malloc(sizeof(*newbuf) * (len + strlen(add) + 1));
if (newbuf == 0)
return (0);
newbuf[0] = 0;
if (buf != 0)
strcat(newbuf, buf);
free(buf);
strcat(newbuf, add);
return (newbuf);
}
int main() {
int sockfd, connfd, len;
struct sockaddr_in servaddr, cli;
// socket create and verification
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {
printf("socket creation failed...\n");
exit(0);
}
else
printf("Socket successfully created..\n");
bzero(&servaddr, sizeof(servaddr));
// assign IP, PORT
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(2130706433); //127.0.0.1
servaddr.sin_port = htons(8081);
// Binding newly created socket to given IP and verification
if ((bind(sockfd, (const struct sockaddr *)&servaddr, sizeof(servaddr))) != 0) {
printf("socket bind failed...\n");
exit(0);
}
else
printf("Socket successfully binded..\n");
if (listen(sockfd, 10) != 0) {
printf("cannot listen\n");
exit(0);
}
len = sizeof(cli);
connfd = accept(sockfd, (struct sockaddr *)&cli, &len);
if (connfd < 0) {
printf("server acccept failed...\n");
exit(0);
}
else
printf("server acccept the client...\n");
}#include <sys/select.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <strings.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
typedef struct s_client {
int id;
char *buffer;
}t_client;
typedef struct s_server {
int sockfd;
int count;
int maxfd;
char write[42];
char read[1001];
t_client clients[65536];
fd_set read_fds;
fd_set write_fds;
fd_set current_fds;
} t_server;
void fatal() {
write(2, "Fatal error\n", 13);
exit(1);
}
int extract_message(char **buf, char **msg)
{
char *newbuf;
int i;
*msg = 0;
if (*buf == 0)
return (0);
i = 0;
while ((*buf)[i])
{
if ((*buf)[i] == '\n')
{
newbuf = calloc(1, sizeof(*newbuf) * (strlen(*buf + i + 1) + 1));
if (newbuf == 0)
return (-1);
strcpy(newbuf, *buf + i + 1);
*msg = *buf;
(*msg)[i + 1] = 0;
*buf = newbuf;
return (1);
}
i++;
}
return (0);
}
char *str_join(char *buf, char *add)
{
char *newbuf;
int len;
if (buf == 0)
len = 0;
else
len = strlen(buf);
newbuf = malloc(sizeof(*newbuf) * (len + strlen(add) + 1));
if (newbuf == 0)
return (0);
newbuf[0] = 0;
if (buf != 0)
strcat(newbuf, buf);
free(buf);
strcat(newbuf, add);
return (newbuf);
}
void ft_broadcast(int sender, t_server *server, char*msg) {
for (int fd = 0; fd <= server->maxfd; fd++) {
if (FD_ISSET(fd, &server->write_fds) && fd != sender) {
send(fd, msg, strlen(msg), 0);
}
}
}
void ft_send_msg (int sender, t_server *server) {
char *msg;
while (extract_message(&server->clients[sender].buffer, &msg)) {
sprintf(server->write, "client %d: ", server->clients[sender].id);
ft_broadcast(sender, server, server->write);
ft_broadcast(sender, server, msg);
free(msg);
}
}
void ft_remove_cli(int sender, t_server * server) {
FD_CLR(sender, &server->current_fds);
close(sender);
if (server->clients[sender].buffer) {
free(server->clients[sender].buffer);
}
server->clients[sender].buffer = (NULL);
sprintf(server->write, "server: client %d just left\n", server->clients[sender].id);
ft_broadcast(sender, server, server->write);
}
int ft_read_msg (int sender, t_server * server) {
int bytes = recv(sender, server->read, 1000, 0);
if (bytes <= 0) {
ft_remove_cli(sender, server);
return - 1;
}
server->read[bytes] = 0;
server->clients[sender].buffer = str_join(server->clients[sender].buffer, server->read);
ft_send_msg(sender, server);
return 0;
}
void ft_config_srv (t_server *server, uint16_t port) {
struct sockaddr_in addrsrv;
bzero(&addrsrv, sizeof(addrsrv));
server->sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (server->sockfd < 0 ) {
fatal();
}
FD_ZERO(&server->current_fds);
FD_SET(server->sockfd, &server->current_fds);
addrsrv.sin_family = AF_INET;
addrsrv.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
addrsrv.sin_port = htons(port);
server->maxfd = server->sockfd;
if (bind(server->sockfd, (const struct sockaddr *)&addrsrv, sizeof(addrsrv)) < 0)
fatal();
if (listen(server->sockfd, 65536) < 0)
fatal();
}
void ft_accept_cli(t_server *server) {
struct sockaddr_in addrcli;
socklen_t len;
bzero(&addrcli, sizeof(addrcli));
len = sizeof(addrcli);
int clifd = accept(server->sockfd, (struct sockaddr *)&addrcli, &len);
if (clifd < 0 ) {
fatal();
}
FD_SET(clifd, &server->current_fds);
//Save
server->maxfd =clifd > server->maxfd ? clifd: server->maxfd;
server->clients[clifd].id = server->count++;
server->clients[clifd].buffer = NULL;
//Notify
sprintf(server->write, "server: client %d just arrived\n", server->clients[clifd].id);
ft_broadcast(clifd, server, server->write);
}
int main (int argc, char **arg) {
t_server server;
if (argc != 2) {
write(2, "Wrong number of arguments\n", 27);
exit(1);
}
bzero(&server, sizeof(server));
ft_config_srv(&server, atoi(arg[1]));
while (1) {
server.read_fds= server.current_fds;
server.write_fds= server.current_fds;
if (select(server.maxfd + 1, &server.read_fds, &server.write_fds, NULL, NULL) < 0) {
fatal();
}
for (int fd = 0; fd <= server.maxfd; fd++) {
if (FD_ISSET(fd, &server.read_fds)) {
if (fd == server.sockfd) {
ft_accept_cli(&server);
} else {
if (ft_read_msg(fd, &server) < 0)
break;
}
}
}
}
return 0;
}Execute
Terminal A
cc mini_srv.c -o mini_srv
./mini_srv 8080Terminal B
nc 127.0.0.1 8080Terminal C
nc 127.0.0.1 8080Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels