working on making game lobbies and joining them
This commit is contained in:
24
Makefile
24
Makefile
@@ -4,8 +4,8 @@ CC =gcc
|
||||
CFLAGS =-g
|
||||
CPPFLAGS =-c -g -Wall -pedantic -Wextra
|
||||
LDFLAGS =-lSDL2 -lm -lSDL2main -lSDL2_image
|
||||
LDFLAGS +=-L/usr/local/lib -lSDL2_ttf
|
||||
INCFLAGS = -I. -Iinclude
|
||||
LDFLAGS +=-L/usr/local/lib -lSDL2_ttf -lSDL2_net
|
||||
INCFLAGS = -I/usr/local/include/SDL2 -Iinclude
|
||||
|
||||
|
||||
INC =include/
|
||||
@@ -19,7 +19,7 @@ ifeq ($(debug),on)
|
||||
CPPFLAGS += -Ddebug
|
||||
endif
|
||||
|
||||
BINARIES = game client_test server_test
|
||||
BINARIES = game client server
|
||||
|
||||
all : $(BINARIES)
|
||||
|
||||
@@ -63,6 +63,17 @@ $(OBJ)game.o : game.c $(INC)game.h | $(OBJ)
|
||||
$(OBJ)overworld.o : overworld.c $(INC)overworld.h | $(OBJ)
|
||||
$(CC) $(CPPFLAGS) -o $@ $< $(INCFLAGS)
|
||||
|
||||
$(OBJ)net.o : net.c $(INC)net.h | $(OBJ)
|
||||
$(CC) $(CPPFLAGS) -o $@ $< $(INCFLAGS)
|
||||
|
||||
$(OBJ)client.o : client.c $(INC)net.h | $(OBJ)
|
||||
$(CC) $(CPPFLAGS) -o $@ $< $(INCFLAGS)
|
||||
|
||||
$(OBJ)server.o : server.c $(INC)net.h | $(OBJ)
|
||||
$(CC) $(CPPFLAGS) -o $@ $< $(INCFLAGS)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## --- LIBRARY FILES ---
|
||||
@@ -73,14 +84,15 @@ $(OBJ)overworld.o : overworld.c $(INC)overworld.h | $(OBJ)
|
||||
#$(BIN) : $(OBJ) | $(BIN)
|
||||
# $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS)
|
||||
|
||||
$(BIN)client_test : $(OBJ)client_test.o | $(BIN)
|
||||
$(BIN)client : $(OBJ)client.o | $(BIN)
|
||||
$(CC) $(CFLAGS) -o $@ $< $(LDFLAGS)
|
||||
|
||||
$(BIN)server_test: $(OBJ)server_test.o | $(BIN)
|
||||
$(BIN)server: $(OBJ)server.o | $(BIN)
|
||||
$(CC) $(CFLAGS) -o $@ $< $(LDFLAGS)
|
||||
|
||||
$(BIN)game : $(OBJ)main.o $(OBJ)input.o $(OBJ)battle.o $(OBJ)game.o\
|
||||
$(OBJ)options.o $(OBJ)host.o $(OBJ)join.o $(OBJ)overworld.o | $(BIN)
|
||||
$(OBJ)options.o $(OBJ)host.o $(OBJ)join.o $(OBJ)overworld.o $(OBJ)net.o\
|
||||
| $(BIN)
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
|
||||
|
||||
$(BINARIES) : % : $(BIN)%
|
||||
|
||||
12
README.md
12
README.md
@@ -7,18 +7,18 @@ DEPENDANCIES
|
||||
SDL CORE:
|
||||
use SDL 2.24.x
|
||||
|
||||
https://github.com/libsdl-org/SDL.git
|
||||
git clone https://github.com/libsdl-org/SDL.git
|
||||
cd SDL
|
||||
git checkout release-2.24.x
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
sudo make install
|
||||
cmake .. -DCMAKE_POLICY_VERSION_MINIMUM=3.5
|
||||
sudo make install -j
|
||||
|
||||
SDL IMAGE:
|
||||
use SDL_Image 2.8.x
|
||||
|
||||
https://github.com/libsdl-org/SDL_image.git
|
||||
git clone https://github.com/libsdl-org/SDL_image.git
|
||||
cd SDL_image
|
||||
git checkout release-2.8.x
|
||||
mkdir build
|
||||
@@ -30,7 +30,7 @@ sudo make install
|
||||
SDL_Net:
|
||||
use SDL_Net 2.2.x
|
||||
|
||||
https://github.com/libsdl-org/SDL_net.git
|
||||
git clone https://github.com/libsdl-org/SDL_net.git
|
||||
cd SDL_net
|
||||
git checkout release-2.2.x
|
||||
mkdir build
|
||||
@@ -41,7 +41,7 @@ sudo make install
|
||||
SDL_ttf
|
||||
use SDL_ttf 2.24.x
|
||||
|
||||
https://github.com/libsdl-org/SDL_ttf.git
|
||||
git clone https://github.com/libsdl-org/SDL_ttf.git
|
||||
cd SDL_ttf
|
||||
git checkout release-2.24.x
|
||||
mkdir build
|
||||
|
||||
210
host.c
210
host.c
@@ -17,27 +17,148 @@
|
||||
int over_object;
|
||||
|
||||
char player_names[MAX_PLAYERS][MAX_NAMESZ];
|
||||
char last_sent_name[MAX_NAMESZ];
|
||||
char temp_name[MAX_NAMESZ];
|
||||
char lobby_name[MAX_NAMESZ];
|
||||
char lobby_name_perm[MAX_NAMESZ];
|
||||
int num_players = 1;
|
||||
|
||||
char *get_this_name(int i)
|
||||
{
|
||||
if(i >= 0 && i < MAX_PLAYERS){ return player_names[i]; }
|
||||
return NULL;
|
||||
}
|
||||
int lobby_has_name = 0;
|
||||
|
||||
|
||||
void host_game(){
|
||||
int i;
|
||||
PRINT_M(HOST state)
|
||||
|
||||
SDL_Point mouse_pos;
|
||||
|
||||
SDL_Rect set_name_rect, name_rect, player_name_rect;
|
||||
SDL_Rect player_rects[MAX_PLAYERS];
|
||||
SDL_Rect player_name_rects[MAX_PLAYERS];
|
||||
SDL_Rect start_rect;
|
||||
|
||||
TTF_Font* font;
|
||||
SDL_Color white = {255, 255, 255, 0};
|
||||
SDL_Surface *set_name_surf;
|
||||
SDL_Surface *start_surf;
|
||||
SDL_Surface *lobby_name_surf;
|
||||
|
||||
SDL_Texture *set_name_tex;
|
||||
SDL_Texture *lobby_name_tex;
|
||||
SDL_Texture *start_tex;
|
||||
|
||||
SDL_Surface *player_name_surfs[MAX_PLAYERS];
|
||||
SDL_Surface *player_tempname_surf;
|
||||
SDL_Texture *player_name_texs[MAX_PLAYERS];
|
||||
SDL_Texture *player_tempname_tex;
|
||||
|
||||
|
||||
|
||||
char *get_this_name(int i)
|
||||
{
|
||||
|
||||
if(!lobby_has_name) {
|
||||
if(i == -1){return lobby_name; }
|
||||
if(i == 0) { return lobby_name_perm; }
|
||||
}
|
||||
else{
|
||||
if(i == -1) { return temp_name; }
|
||||
if(i >= 0 && i < MAX_PLAYERS){
|
||||
return player_names[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void render_lobby()
|
||||
{
|
||||
int i;
|
||||
|
||||
player_tempname_surf= TTF_RenderText_Solid(font, temp_name, white);
|
||||
player_tempname_tex = SDL_CreateTextureFromSurface(renderer, player_tempname_surf);
|
||||
|
||||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
|
||||
SDL_RenderClear(renderer);
|
||||
|
||||
//set name button
|
||||
SDL_SetRenderDrawColor(renderer, 64, 64, 64,255);
|
||||
SDL_RenderFillRect(renderer, &set_name_rect);
|
||||
SDL_RenderCopy(renderer, set_name_tex, NULL, &(set_name_rect));
|
||||
|
||||
//player fields
|
||||
for(i = 0; i < MAX_PLAYERS; i++)
|
||||
{
|
||||
player_name_rects[i].w = (player_rects[0].w / MAX_NAMESZ) * strlen(player_names[i]);
|
||||
player_name_surfs[i] = TTF_RenderText_Solid(font, player_names[i], white);
|
||||
player_name_texs[i] = SDL_CreateTextureFromSurface(renderer, player_name_surfs[i]);
|
||||
SDL_RenderFillRect(renderer, &(player_rects[i]));
|
||||
SDL_RenderCopy(renderer, player_name_texs[i], NULL, &(player_name_rects[i]));
|
||||
}
|
||||
//name field
|
||||
player_name_rect.w = (name_rect.w / MAX_NAMESZ) * strlen(temp_name);
|
||||
SDL_RenderFillRect(renderer, &name_rect);
|
||||
SDL_RenderCopy(renderer, player_tempname_tex, NULL, &player_name_rect);
|
||||
|
||||
//start game button
|
||||
SDL_RenderFillRect(renderer, &start_rect);
|
||||
SDL_RenderCopy(renderer, start_tex, NULL, &(start_rect));
|
||||
|
||||
|
||||
SDL_RenderPresent(renderer);
|
||||
|
||||
player_tempname_surf= TTF_RenderText_Solid(font, temp_name, white);
|
||||
player_tempname_tex = SDL_CreateTextureFromSurface(renderer, player_tempname_surf);
|
||||
|
||||
SDL_FreeSurface(player_tempname_surf);
|
||||
SDL_DestroyTexture(player_tempname_tex);
|
||||
for(i = 0; i < MAX_PLAYERS; i++)
|
||||
{
|
||||
SDL_FreeSurface(player_name_surfs[i]);
|
||||
SDL_DestroyTexture(player_name_texs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void render_lobby_name()
|
||||
{
|
||||
|
||||
lobby_name_surf = TTF_RenderText_Solid(font, lobby_name, white);
|
||||
lobby_name_tex = SDL_CreateTextureFromSurface(renderer, lobby_name_surf);
|
||||
|
||||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
|
||||
SDL_RenderClear(renderer);
|
||||
|
||||
//set lobby name button
|
||||
SDL_SetRenderDrawColor(renderer, 64, 64, 64,255);
|
||||
SDL_RenderFillRect(renderer, &set_name_rect);
|
||||
SDL_RenderCopy(renderer, set_name_tex, NULL, &(set_name_rect));
|
||||
|
||||
//name field
|
||||
player_name_rect.w = (name_rect.w / MAX_NAMESZ) * strlen(lobby_name);
|
||||
SDL_RenderFillRect(renderer, &name_rect);
|
||||
SDL_RenderCopy(renderer, lobby_name_tex, NULL, &player_name_rect);
|
||||
|
||||
//start game button
|
||||
SDL_RenderFillRect(renderer, &start_rect);
|
||||
SDL_RenderCopy(renderer, start_tex, NULL, &(start_rect));
|
||||
|
||||
SDL_RenderPresent(renderer);
|
||||
|
||||
}
|
||||
|
||||
void render_main()
|
||||
{
|
||||
SDL_GetMouseState(&(mouse_pos.x), &(mouse_pos.y));
|
||||
|
||||
if(SDL_PointInRect(&mouse_pos, &start_rect)){
|
||||
over_object = START_GAME_BUTTON;
|
||||
}
|
||||
else if(SDL_PointInRect(&mouse_pos, &set_name_rect)){
|
||||
over_object = SET_NAME_BUTTON;
|
||||
}
|
||||
|
||||
handle_event(&event);
|
||||
|
||||
if(lobby_has_name){ render_lobby(); }
|
||||
else{ render_lobby_name(); }
|
||||
}
|
||||
|
||||
void host_game(){
|
||||
int i;
|
||||
PRINT_M(HOST state)
|
||||
|
||||
over_object = NO_OBJECT;
|
||||
|
||||
strcpy(player_names[0], "player_1");
|
||||
@@ -45,14 +166,13 @@ void host_game(){
|
||||
strcpy(player_names[2], "no_player_3");
|
||||
strcpy(player_names[3], "no_player_4");
|
||||
|
||||
TTF_Font* font = TTF_OpenFont("assets/font.ttf", 24);
|
||||
SDL_Color white = {255, 255, 255, 0};
|
||||
SDL_Surface *set_name_surf = TTF_RenderText_Solid(font, "set name", white);
|
||||
SDL_Surface *start_surf = TTF_RenderText_Solid(font, "start game", white);
|
||||
|
||||
SDL_Texture *set_name_tex = SDL_CreateTextureFromSurface(renderer, set_name_surf);
|
||||
SDL_Texture *start_tex = SDL_CreateTextureFromSurface(renderer, start_surf);
|
||||
font = TTF_OpenFont("assets/font.ttf", 24);
|
||||
set_name_surf = TTF_RenderText_Solid(font, "set name", white);
|
||||
start_surf = TTF_RenderText_Solid(font, "start game", white);
|
||||
lobby_name_surf = TTF_RenderText_Solid(font, lobby_name, white);
|
||||
|
||||
set_name_tex = SDL_CreateTextureFromSurface(renderer, set_name_surf);
|
||||
start_tex = SDL_CreateTextureFromSurface(renderer, start_surf);
|
||||
|
||||
|
||||
set_name_rect.w = DEF_WINDOW_WIDTH >> 3;
|
||||
@@ -99,60 +219,10 @@ void host_game(){
|
||||
|
||||
SDL_StartTextInput();
|
||||
SDL_SetTextInputRect(&name_rect);
|
||||
SDL_Surface *player_name_surfs[MAX_PLAYERS];
|
||||
SDL_Texture *player_name_texs[MAX_PLAYERS];
|
||||
|
||||
|
||||
while(running)
|
||||
{
|
||||
|
||||
SDL_GetMouseState(&(mouse_pos.x), &(mouse_pos.y));
|
||||
|
||||
if(SDL_PointInRect(&mouse_pos, &start_rect))
|
||||
{
|
||||
over_object = START_GAME_BUTTON;
|
||||
}
|
||||
else if(SDL_PointInRect(&mouse_pos, &set_name_rect))
|
||||
{
|
||||
over_object = SET_NAME_BUTTON;
|
||||
}
|
||||
|
||||
|
||||
handle_event(&event);
|
||||
|
||||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
|
||||
SDL_RenderClear(renderer);
|
||||
|
||||
//set name button
|
||||
SDL_SetRenderDrawColor(renderer, 64, 64, 64,255);
|
||||
SDL_RenderFillRect(renderer, &set_name_rect);
|
||||
SDL_RenderCopy(renderer, set_name_tex, NULL, &(set_name_rect));
|
||||
|
||||
//player fields
|
||||
for(i = 0; i < MAX_PLAYERS; i++)
|
||||
{
|
||||
player_name_rects[i].w = (player_rects[0].w / MAX_NAMESZ) * strlen(player_names[i]);
|
||||
player_name_surfs[i] = TTF_RenderText_Solid(font, player_names[i], white);
|
||||
player_name_texs[i] = SDL_CreateTextureFromSurface(renderer, player_name_surfs[i]);
|
||||
SDL_RenderFillRect(renderer, &(player_rects[i]));
|
||||
SDL_RenderCopy(renderer, player_name_texs[i], NULL, &(player_name_rects[i]));
|
||||
}
|
||||
//name field
|
||||
player_name_rect.w = (name_rect.w / MAX_NAMESZ) * strlen(player_names[0]);
|
||||
SDL_RenderFillRect(renderer, &name_rect);
|
||||
SDL_RenderCopy(renderer, player_name_texs[0], NULL, &player_name_rect);
|
||||
|
||||
//start game button
|
||||
SDL_RenderFillRect(renderer, &start_rect);
|
||||
SDL_RenderCopy(renderer, start_tex, NULL, &(start_rect));
|
||||
|
||||
|
||||
SDL_RenderPresent(renderer);
|
||||
for(i = 0; i < MAX_PLAYERS; i++)
|
||||
{
|
||||
SDL_FreeSurface(player_name_surfs[i]);
|
||||
SDL_DestroyTexture(player_name_texs[i]);
|
||||
}
|
||||
render_main();
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
extern SDL_Point mouse_pos;
|
||||
|
||||
#define TITLE 0
|
||||
#define START 1
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
#define START_GAME_BUTTON 2
|
||||
|
||||
extern int over_object;
|
||||
extern int lobby_has_name;
|
||||
|
||||
|
||||
char *get_this_name(int i);
|
||||
|
||||
|
||||
@@ -1,12 +1,48 @@
|
||||
//Troy Rosin
|
||||
|
||||
#ifndef __netcode_h__
|
||||
#define __netcode_h__
|
||||
#ifndef __my_net_h__
|
||||
#define __my_net_h__
|
||||
|
||||
#define PORT 36911
|
||||
|
||||
void init_network();
|
||||
#define SERVER "localhost"
|
||||
|
||||
#define PACKSZ 1024
|
||||
|
||||
enum pack_type{
|
||||
G_STATE, S_STATE, HOSTS_REQ, NEW_HOST, JOIN_REQ, U_NAME
|
||||
};
|
||||
|
||||
typedef struct packet{
|
||||
enum pack_type type;
|
||||
char payload[PACKSZ - sizeof(enum pack_type)];
|
||||
} packet;
|
||||
|
||||
|
||||
int read_to_buff(Uint32 *buff, Uint32 *src, Uint32 sz)
|
||||
{
|
||||
if(sz%32){
|
||||
puts("error size must be div by 32");
|
||||
return 0;
|
||||
}
|
||||
for(Uint32 i = 0; i < (sz >> 2); i += 1)
|
||||
{
|
||||
*(buff + i) = SDLNet_Read32(src + i);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int write_to_buff(Uint32 *buff, Uint32 *src, Uint32 sz)
|
||||
{
|
||||
if(sz%32){
|
||||
puts("error size must be div by 32");
|
||||
return 0;
|
||||
}
|
||||
for(Uint32 i = 0; i < (sz >> 2); i += 1)
|
||||
{
|
||||
SDLNet_Write32(*(src + i), (buff + i));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
21
input.c
21
input.c
@@ -153,10 +153,9 @@ void handle_input_host(SDL_Event *e)
|
||||
{
|
||||
int oldlen, inputlen;
|
||||
char tempname[MAX_NAMESZ], *nameptr;
|
||||
nameptr = get_this_name(0);
|
||||
nameptr = get_this_name(-1);
|
||||
strcpy(tempname, nameptr);
|
||||
oldlen = strlen(tempname);
|
||||
inputlen = strlen(e->text.text);
|
||||
|
||||
switch(e->type)
|
||||
{
|
||||
@@ -177,14 +176,26 @@ void handle_input_host(SDL_Event *e)
|
||||
}
|
||||
break;
|
||||
case SDL_TEXTINPUT:
|
||||
inputlen = strlen(e->text.text);
|
||||
PRINT_M(got text input event)
|
||||
if(oldlen + inputlen > MAX_NAMESZ -1){ break; }
|
||||
strcat(tempname, e->text.text);
|
||||
strcpy(nameptr, tempname);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("got event type: %u\n", e->type);
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
switch(over_object)
|
||||
{
|
||||
case NO_OBJECT:
|
||||
break;
|
||||
case SET_NAME_BUTTON:
|
||||
strcpy(get_this_name(0), nameptr);
|
||||
break;
|
||||
case START_GAME_BUTTON:
|
||||
if(strlen(get_this_name(0)) >= 1){
|
||||
lobby_has_name = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
48
net.h
48
net.h
@@ -1,48 +0,0 @@
|
||||
//Troy Rosin
|
||||
#ifndef __my_net_h__
|
||||
#define __my_net_h__
|
||||
|
||||
#define PORT 36911
|
||||
|
||||
#define SERVER "localhost"
|
||||
|
||||
#define PACKSZ 1024
|
||||
|
||||
enum pack_type{
|
||||
G_STATE, S_STATE, HOSTS_REQ, NEW_HOST, JOIN_REQ, U_NAME
|
||||
};
|
||||
|
||||
typedef struct packet{
|
||||
enum pack_type type;
|
||||
char payload[PACKSZ - sizeof(enum pack_type)];
|
||||
} packet;
|
||||
|
||||
|
||||
int read_to_buff(Uint32 *buff, Uint32 *src, Uint32 sz)
|
||||
{
|
||||
if(sz%32){
|
||||
puts("error size must be div by 32");
|
||||
return 0;
|
||||
}
|
||||
for(Uint32 i = 0; i < (sz >> 2); i += 1)
|
||||
{
|
||||
*(buff + i) = SDLNet_Read32(src + i);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int write_to_buff(Uint32 *buff, Uint32 *src, Uint32 sz)
|
||||
{
|
||||
if(sz%32){
|
||||
puts("error size must be div by 32");
|
||||
return 0;
|
||||
}
|
||||
for(Uint32 i = 0; i < (sz >> 2); i += 1)
|
||||
{
|
||||
SDLNet_Write32(*(src + i), (buff + i));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
3
server.c
3
server.c
@@ -89,7 +89,6 @@ void game_server()
|
||||
break;
|
||||
case U_NAME:
|
||||
PRINT_M("got to update name state");
|
||||
flag = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -110,13 +109,11 @@ void game_server()
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
SDLNet_TCP_Close(sock);
|
||||
SDLNet_Quit();
|
||||
SDL_Quit();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
137
server_test.c
137
server_test.c
@@ -1,137 +0,0 @@
|
||||
/*
|
||||
** server.c -- a stream socket server demo
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/wait.h>
|
||||
#include <signal.h>
|
||||
|
||||
#define PORT "3490" // the port users will be connecting to
|
||||
|
||||
#define BACKLOG 10 // how many pending connections queue will hold
|
||||
|
||||
void sigchld_handler(int s)
|
||||
{
|
||||
(void)s; // quiet unused variable warning
|
||||
|
||||
// waitpid() might overwrite errno, so we save and restore it:
|
||||
int saved_errno = errno;
|
||||
|
||||
while(waitpid(-1, NULL, WNOHANG) > 0);
|
||||
|
||||
errno = saved_errno;
|
||||
}
|
||||
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
// listen on sock_fd, new connection on new_fd
|
||||
int sockfd, new_fd;
|
||||
struct addrinfo hints, *servinfo, *p;
|
||||
struct sockaddr_storage their_addr; // connector's address info
|
||||
socklen_t sin_size;
|
||||
struct sigaction sa;
|
||||
int yes=1;
|
||||
char s[INET6_ADDRSTRLEN];
|
||||
int rv;
|
||||
|
||||
memset(&hints, 0, sizeof hints);
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_flags = AI_PASSIVE; // use my IP
|
||||
|
||||
if ((rv = getaddrinfo(NULL, PORT, &hints, &servinfo)) != 0) {
|
||||
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// loop through all the results and bind to the first we can
|
||||
for(p = servinfo; p != NULL; p = p->ai_next) {
|
||||
if ((sockfd = socket(p->ai_family, p->ai_socktype,
|
||||
p->ai_protocol)) == -1) {
|
||||
perror("server: socket");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes,
|
||||
sizeof(int)) == -1) {
|
||||
perror("setsockopt");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
|
||||
close(sockfd);
|
||||
perror("server: bind");
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
freeaddrinfo(servinfo); // all done with this structure
|
||||
|
||||
if (p == NULL) {
|
||||
fprintf(stderr, "server: failed to bind\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (listen(sockfd, BACKLOG) == -1) {
|
||||
perror("listen");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
sa.sa_handler = sigchld_handler; // reap all dead processes
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags = SA_RESTART;
|
||||
if (sigaction(SIGCHLD, &sa, NULL) == -1) {
|
||||
perror("sigaction");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("server: waiting for connections...\n");
|
||||
|
||||
while(1) { // main accept() loop
|
||||
sin_size = sizeof their_addr;
|
||||
new_fd = accept(sockfd, (struct sockaddr *)&their_addr,
|
||||
&sin_size);
|
||||
if (new_fd == -1) {
|
||||
perror("accept");
|
||||
continue;
|
||||
}
|
||||
|
||||
inet_ntop(their_addr.ss_family,
|
||||
get_in_addr((struct sockaddr *)&their_addr),
|
||||
s, sizeof s);
|
||||
printf("server: got connection from %s\n", s);
|
||||
|
||||
if (!fork()) { // this is the child process
|
||||
close(sockfd); // child doesn't need the listener
|
||||
if (send(new_fd, "Hello, world!", 13, 0) == -1)
|
||||
perror("send");
|
||||
close(new_fd);
|
||||
exit(0);
|
||||
}
|
||||
close(new_fd); // parent doesn't need this
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user