Server:
static void Init_Server(int port)
{
int err, flags;
struct sockaddr_in server_addr;
s_server_fd = socket(AF_INET, SOCK_STREAM, 0);
if (s_server_fd < 0)
on_error("Could not create server_addr socket: %s\n", strerror(errno))
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
int opt_val = 1;
setsockopt(s_server_fd, SOL_SOCKET, SO_REUSEADDR, &opt_val, sizeof(opt_val));
err = bind(s_server_fd, (struct sockaddr *) &server_addr, sizeof(server_addr));
if (err < 0)
on_error("Could not bind server_addr socket: %s\n", strerror(errno));
flags = fcntl(s_server_fd, F_GETFL, 0);
if (flags < 0)
on_error("Could not get server_addr socket flags: %s\n", strerror(errno))
err = fcntl(s_server_fd, F_SETFL, flags | O_NONBLOCK);
if (err < 0) on_error("Could set server_addr socket to be non blocking: %s\n", strerror(errno));
err = listen(s_server_fd, SOMAXCONN);
if (err < 0)
on_error("Could not listen: %s\n", strerror(errno));
}
static int Accept_Coming ()
{
int err;
int flags;
int client_fd;
struct sockaddr client_addr;
socklen_t client_len;
client_fd = accept(s_server_fd, &client_addr, &client_len);
client_len = sizeof(client_addr);
if (client_fd < 0)
{
if (errno == EWOULDBLOCK || errno == EAGAIN)
return 0;
on_error("Accept failed (should this be fatal?): %s\n", strerror(errno));
}
flags = fcntl(client_fd, F_GETFL, 0);
if (flags < 0)
on_error("Could not get client socket flags: %s\n", strerror(errno));
err = fcntl(client_fd, F_SETFL, flags | O_NONBLOCK);
if (err < 0)
on_error("Could not set client socket to be non blocking: %s\n", strerror(errno));
return client_fd;
}
///Another way to use select maxfd+1(at least +1) to make non-block server///
FD_ZERO(&svfset);
FD_SET(s_serversocket, &svfset);
while( s_thread_work )
{
rdset = svfset;
//use select monitor all sockets of list
if (select(maxfd+1, &rdset, NULL, NULL, NULL) == -1)
{
s_thread_work = 0; //exit while loop
printf("Server select failure \n");
}
/////////New client and data receive/////////
node_ptr = List_NetGetFirstNode();
while( node_ptr )
{
if (FD_ISSET(node_ptr->socketfd, &rdset))
{
//if (current_socket == s_serversocket)
if( node_ptr->socketfd == s_serversocket )
{
/* Handle new connections */
addrlen = sizeof(clientaddr);
memset(&clientaddr, 0, sizeof(clientaddr));
acceptfd = accept(s_serversocket, (struct sockaddr*)&clientaddr, &addrlen);
if (acceptfd <= -1)
{
printf("Server accept error \n");
}
else
{
FD_SET(acceptfd, &svfset);
if (acceptfd > maxfd)
{
/* Keep track of the maximum */
maxfd = acceptfd;
}
List_NetAddRear(acceptfd);
printf("New connection IP %s\n", inet_ntoa(clientaddr.sin_addr));
printf("Accept / maxfd = %d\n\n", maxfd);
}
}
else
{
len = recv(node_ptr->socketfd, buf, sizeof(buf), 0);
node_ptr->tick_last = GetNowTick();
if (len > 0)
{
//do your work
Buf_Job(node_ptr->socketfd, buf, len);
}
//else if (len == -1)
else
{
FD_CLR(node_ptr->socketfd, &svfset);
if (node_ptr->socketfd >= maxfd)
{
/* Keep track of the maximum */
maxfd--;
}
shutdown(node_ptr->socketfd, SHUT_RDWR);
close(node_ptr->socketfd);
printf("Disconnect remove socket %d\n", node_ptr->socketfd);
printf("Disconnect and maxfd = %d\n", maxfd);
node_ext.next = node_ptr->next;
List_NetDeletebyNode(node_ptr);
node_ptr = &node_ext;
}
}
}//if (FD_ISSET(node_ptr->socketfd, &rdset))
node_ptr = node_ptr->next;
}//while(node)
}
Client:
opts = fcntl(sockfd, F_GETFL);
if(opts < 0)
{
fprintf(stderr, "fcntl(F_GETFL) failedn");
}
opts = (opts | O_NONBLOCK);
if(fcntl(sockfd, F_SETFL, opts) < 0)
{
fprintf(stderr, "fcntl(F_SETFL) failedn");
}
source download:
http://www.mediafire.com/file/d649td73n6cwx74/nonblock_socket.zip
http://www.mediafire.com/file/5c7g9bt5mh2c6mj/server_multiclient.tar.gz
https://www.mediafire.com/file/k64168ezb925z6g/linux_server_client.tar.gz
沒有留言:
張貼留言