I am trying to implement a socket library. It was all doing ok, until I reach accept function. I looked into the stack overflow, and I guy said it won't return until a client is being connected through this but if it is not in blockmode. So, I would like to know: HOW TO CHANGE LISTEN TO NONBLOCK mode?
Here is my header:
#ifndef NET_SOCKET_H
#define NET_SOCKET_H
#ifdef __cplusplus
extern "C" {
#endif
#if defined(WIN32) || defined(WINDOWS_XP)
#include <winsock2.h>
#endif
#include <type-of/include/type.h>
#include <unistd.h>
#define NET_SOCK_ALLOCATED 1
typedef struct NetSocket NET_SOCK;
typedef struct sockaddr_in NET_ADDR_IN;
typedef struct sockaddr NET_ADDR;
struct NetSocket {
struct {
B32 sys; // PF_INET or PF_UNIX
B32 data; // SOCK_STREAM or SOCK_DGRAM
B32 mode; // IPPROTO_TCP or IPPROTO_UDP
} from;
#if defined(WIN32) || defined(WINDOWS_XP)
SOCKET sock;
#else
B32 sock;
#endif
B8 * host;
NET_ADDR_IN to;
BIT status;
STATUS(*open)(NET_SOCK * net);
STATUS(*tie)(NET_SOCK * server);
STATUS(*wait)(NET_SOCK * net, B32 max);
STATUS(*join)(NET_SOCK * server, NET_SOCK * client);
STATUS(*in)(NET_SOCK * client);
void (*close)(NET_SOCK * net);
void (*pop)(NET_SOCK * net);
};
NET_SOCK net_sock_std(B8U * host, B32U port);
NET_SOCK * net_sock_push(B8U * host, B32U port);
void net_sock_zero(NET_SOCK * net);
STATUS net_sock_open(NET_SOCK * net);
STATUS net_sock_tie(NET_SOCK * server);
STATUS net_sock_wait(NET_SOCK * net, B32 max);
STATUS net_sock_join(NET_SOCK * server, NET_SOCK * client);
STATUS net_sock_in(NET_SOCK * client);
STATUS net_sock_put(NET_SOCK * net);
void net_sock_close(NET_SOCK * net);
void net_sock_pop(NET_SOCK * net);
void winsock_start();
void winsock_stop();
#ifdef __cplusplus
}
#endif
#endif /* NET_SOCKET_H */
Here is my source:
#include "net_socket.h"
void net_sock_function(NET_SOCK * net){
if(net){
net->open = net_sock_open;
net->tie = net_sock_tie;
net->wait = net_sock_wait;
net->join = net_sock_join;
net->in = net_sock_in;
net->close = net_sock_close;
net->pop = net_sock_pop;
}
}
NET_SOCK net_sock_std(B8U * host, B32U port){
NET_SOCK net;
net_sock_zero(&net);
if(host)net.host = strdup(host);
if(port)net.to.sin_port = htons(port);
bit_off(&net.status,NET_SOCK_ALLOCATED);
return(net);
}
NET_SOCK * net_sock_push(B8U * host, B32U port){
NET_SOCK * net = malloc(sizeof(NET_SOCK));
net_sock_zero(net);
if(host)net->host = strdup(host);
if(port)net->to.sin_port = htons(port);
bit_on(&net->status,NET_SOCK_ALLOCATED);
return(net);
}
void net_sock_zero(NET_SOCK * net){
if(net){
winsock_start();
net->from.data = SOCK_STREAM;
net->from.mode = IPPROTO_TCP;
if(is_win()){
net->from.sys = AF_INET;
net->to.sin_family = AF_INET;
}
else {
net->from.sys = AF_UNIX;
net->to.sin_family = AF_UNIX;
}
net->sock = -1;
net->host = NULL;
net->to.sin_addr.s_addr = htonl(INADDR_ANY);
net->to.sin_port = 0;
net_sock_function(net);
}
}
STATUS net_sock_open(NET_SOCK * net){
if(!net)return(Off);
if( (net->sock = socket(net->from.sys,net->from.data,net->from.mode)) != -1)return(On);
return(Off);
}
STATUS net_sock_tie(NET_SOCK * server){
if(!server)return(Off);
if(bind(server->sock,(NET_ADDR*)&server->to,sizeof(server->to)) != -1)return(On);
return(Off);
}
STATUS net_sock_wait(NET_SOCK * net, B32 max){
if(!net)return(Off);
if(listen(net->sock,max) != -1)return(On);
return(Off);
}
STATUS net_sock_join(NET_SOCK * server,NET_SOCK * client){
if(!server || !client)return(Off);
B32U clientLen = sizeof(client->to);
while((client->sock = accept(server->sock,(NET_ADDR *)&client->to,&clientLen)) == -1)return(On);
return(Off);
}
STATUS net_sock_in(NET_SOCK * client){
if(!client)return(Off);
if(connect(client->sock,(NET_ADDR *)&client->to,sizeof(client->to)) != -1)return(On);
return(Off);
}
STATUS net_sock_put(NET_SOCK * net){
if(!net)return(Off);
return(Off);
}
void net_sock_close(NET_SOCK * net){
if(is_win())closesocket(net->sock);
else close(net->sock);
}
void net_sock_pop(NET_SOCK * net){
if(net){
if(net->host){
free(net->host);
net->host = NULL;
}
if(bit_is_on(net->status,NET_SOCK_ALLOCATED)){
free(net);
net = NULL;
}
}
}
void winsock_start() {
if (is_win()) {
WORD versionWanted = MAKEWORD(1, 1);
WSADATA wsaData;
WSAStartup(versionWanted, &wsaData);
atexit(winsock_stop);
}
}
void winsock_stop() {
if (is_win()) {
WSACleanup();
}
}
And finally my main:
#include "net_socket.h"
void command_line(B32 c, B8 ** v, B8U ** host, B32U * port) {
B32 i = 1;
while (i < c) {
switch (i) {
case 1:
{
*port = atoi(v[i]);
}
break;
case 2:
{
*host = v[i];
}
break;
}
i++;
}
}
int main(int argc, char** argv) {
B8U * host = NULL;
B32U port = 50;
command_line(argc, argv, &host, &port);
NET_SOCK server = net_sock_std(NULL, port);
if (server.open(&server)) {
if (!host) {
NET_SOCK client = net_sock_std("localhost", port);
printf("server openned in %hu\n", server.to.sin_port);
if (client.open(&client)) {
printf("Server client openned in %hu", client.to.sin_port);
}
if (server.tie(&server) && server.wait(&server, 1)){
printf("\nready\n");
}
while (server.join(&server, &client)){ // I can't get in search mode
printf("searching\n");
}
client.pop(&client);
} else {
NET_SOCK client = net_sock_std(host, port);
if (client.open(&client)) {
printf("client openned in %s %hu\n", host, client.to.sin_port);
while (!client.in(&client)) {
printf("trying to connect\n");
}
printf("bye server\n");
}
}
server.close(&server);
}
server.pop(&server);
return (EXIT_SUCCESS);
}
With the help of my friend Jeremy I found: (IT IS JUST TO SET SERVER SOCK TO OFF)
STATUS net_lock_socket(NET_SOCK * net, STATUS block) {
if (!net || net->sock < 0) return Off;
#if defined(WIN32)
unsigned long mode = block ? 0 : 1;
return (ioctlsocket(net->sock, FIONBIO, &mode) == 0) ? On : Off;
#else
int flags = fcntl(net->sock, F_GETFL, 0);
if (flags == -1) return Off;
flags = block ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK);
return (fcntl(net->sock, F_SETFL, flags) == 0) ? On : Off;
#endif
}