1.TCP服务器类封装
# ifndef _TCP_SERVER_H_
# define _TCP_SERVER_H_
# include <string>
# ifdef __cplusplus
extern "C" {
# endif
# define TCP_PORT_NO 8888
# define TCP_BUFFER_SIZE ( 4 * 1024 )
# define HEART_BEAT_INTERVAL ( 15 )
class Tcp_Server
{
private:
static Tcp_Server * g_object;
Tcp_Server ( ) ;
~ Tcp_Server ( ) ;
private:
static void * tcp_socket_thread_loop ( void * data) ;
static void * tcp_socket_beat_thread_loop ( void * data) ;
void handle_request ( int sockfd) ;
private:
pthread_t m_socketThread;
pthread_t m_socketBeatThread;
int m_sockFd;
int m_connectSockFd;
bool m_run;
public:
static Tcp_Server * get ( void ) ;
int start_tcp_server ( ) ;
int stop_tcp_server ( ) ;
} ;
# ifdef __cplusplus
}
# endif
# endif
2.构建单例模式
Tcp_Server* Tcp_Server:: g_object = NULL ;
Tcp_Server* Tcp_Server:: get ( void )
{
if ( NULL == g_object)
{
g_object = new Tcp_Server;
}
return g_object;
}
3.创建TCP服务器
int Tcp_Server:: start_tcp_server ( )
{
m_sockFd = socket ( AF_INET, SOCK_STREAM, 0 ) ;
if ( m_sockFd < 0 ) {
printf ( "create socket error: %s(errno: %d)\n" , strerror ( errno) , errno) ;
return - 1 ;
}
int optval = 1 ;
int ret = setsockopt ( m_sockFd, SOL_SOCKET, SO_REUSEADDR, & optval, sizeof ( optval) ) ;
if ( ret < 0 )
{
printf ( "Error setting socket option ret:%d\n" , ret) ;
return - 1 ;
}
struct sockaddr_in serverAddr;
memset ( & serverAddr, 0 , sizeof ( serverAddr) ) ;
serverAddr. sin_family = AF_INET;
serverAddr. sin_addr. s_addr = INADDR_ANY;
serverAddr. sin_port = htons ( TCP_PORT_NO) ;
if ( bind ( m_sockFd, ( struct sockaddr * ) & serverAddr, sizeof ( serverAddr) ) < 0 )
{
printf ( "Binding error: please try again in 20sec and make sure no other instance is running\n" ) ;
return - 1 ;
}
if ( - 1 == listen ( m_sockFd, 10 ) )
{
printf ( "listen socket error: %s(errno: %d)\n" , strerror ( errno) , errno) ;
return - 1 ;
}
printf ( "success to create tcp server...\n" ) ;
m_run = true;
pthread_create ( & m_socketThread, NULL , tcp_socket_thread_loop, this) ;
if ( ! m_socketThread) {
printf ( "create m_socketThread failed" ) ;
return - 1 ;
}
pthread_create ( & m_socketBeatThread, NULL , tcp_socket_beat_thread_loop, this) ;
if ( ! m_socketBeatThread) {
printf ( "create m_socketBeatThread failed" ) ;
return - 1 ;
}
return 0 ;
}
4.客户端请求处理线程
void * Tcp_Server :: tcp_socket_thread_loop ( void * data)
{
Tcp_Server * service = ( Tcp_Server * ) data;
while ( service-> m_run)
{
if ( service-> m_connectSockFd < 0 )
{
struct sockaddr_in clientAddr;
socklen_t clientLen = sizeof ( clientAddr) ;
service-> m_connectSockFd = accept ( service-> m_sockFd, ( struct sockaddr * ) & clientAddr, & clientLen) ;
if ( service-> m_connectSockFd < 0 )
{
printf ( "couldn't accept\n" ) ;
continue ;
}
else {
service-> handle_request ( service-> m_connectSockFd) ;
}
}
else {
service-> handle_request ( service-> m_connectSockFd) ;
}
usleep ( 1000 ) ;
}
return NULL ;
}
5.心跳线程维持连接
void * Tcp_Server :: tcp_socket_beat_thread_loop ( void * data)
{
Tcp_Server * service = ( Tcp_Server * ) data;
size_t send_size = 0
while ( service-> m_run)
{
if ( service-> m_connectSockFd >= 0 )
{
std:: string beat = "action:heart beat" ;
send_size = send ( service-> m_connectSockFd, beat. c_str ( ) , beat. size ( ) , MSG_NOSIGNAL) ;
if ( send_size == - 1 )
{
close ( m_service-> m_connectSockFd) ;
service-> m_connectSockFd = - 1 ;
printf ( "client is disconnected...\n" ) ;
}
else {
printf ( "send client:%s\n" , beat. c_str ( ) ) ;
}
}
sleep ( HEART_BEAT_INTERVAL) ;
}
return NULL ;
}
6.客户端请求处理函数
void Tcp_Server :: handle_request ( int sockfd)
{
char * read_buffer = new char [ TCP_BUFFER_SIZE] ;
int size = read ( sockfd, read_buffer, TCP_BUFFER_SIZE) ;
printf ( "recv client:%s\n" , read_buffer) ;
delete [ ] read_buffer;
std:: string response = "hello this is http server..." ;
send ( sockfd, response. c_str ( ) , response. size ( ) , MSG_NOSIGNAL) ;
printf ( "send client:%s\n" , response. c_str ( ) ) ;
}
7.调试打印
1.客户端调试日志
2.服务端调试日志
8.源码如下
1.tcp_server.h源码
# ifndef _TCP_SERVER_H_
# define _TCP_SERVER_H_
# include <string>
# ifdef __cplusplus
extern "C" {
# endif
# define TCP_PORT_NO 8888
# define TCP_BUFFER_SIZE ( 4 * 1024 )
# define HEART_BEAT_INTERVAL ( 15 )
class Tcp_Server
{
private :
static Tcp_Server * g_object;
Tcp_Server ( ) ;
~ Tcp_Server ( ) ;
private :
static void * tcp_socket_thread_loop ( void * data) ;
static void * tcp_socket_beat_thread_loop ( void * data) ;
void handle_request ( int sockfd) ;
private :
pthread_t m_socketThread;
pthread_t m_socketBeatThread;
int m_sockFd;
int m_connectSockFd;
bool m_run;
public :
static Tcp_Server * get ( void ) ;
int start_tcp_server ( ) ;
int stop_tcp_server ( ) ;
} ;
# ifdef __cplusplus
}
# endif
# endif
2.tcp_server.cpp源码
# include <sys/socket.h>
# include <netinet/in.h>
# include <pthread.h>
# include <string.h>
# include <unistd.h>
# include "tcp_server.h"
Tcp_Server* Tcp_Server:: g_object = NULL ;
Tcp_Server* Tcp_Server :: get ( void )
{
if ( NULL == g_object)
{
g_object = new Tcp_Server;
}
return g_object;
}
void Tcp_Server :: handle_request ( int sockfd)
{
char * read_buffer = new char [ TCP_BUFFER_SIZE] ;
int size = read ( sockfd, read_buffer, TCP_BUFFER_SIZE) ;
printf ( "recv client:%s\n" , read_buffer) ;
delete [ ] read_buffer;
std:: string response = "hello this is http server..." ;
send ( sockfd, response. c_str ( ) , response. size ( ) , MSG_NOSIGNAL) ;
printf ( "send client:%s\n" , response. c_str ( ) ) ;
}
void * Tcp_Server :: tcp_socket_thread_loop ( void * data)
{
Tcp_Server * service = ( Tcp_Server * ) data;
while ( service-> m_run)
{
if ( service-> m_connectSockFd < 0 )
{
struct sockaddr_in clientAddr;
socklen_t clientLen = sizeof ( clientAddr) ;
service-> m_connectSockFd = accept ( service-> m_sockFd, ( struct sockaddr * ) & clientAddr, & clientLen) ;
if ( service-> m_connectSockFd < 0 )
{
printf ( "couldn't accept\n" ) ;
continue ;
}
else {
service-> handle_request ( service-> m_connectSockFd) ;
}
}
else {
service-> handle_request ( service-> m_connectSockFd) ;
}
usleep ( 1000 ) ;
}
return NULL ;
}
void * Tcp_Server :: tcp_socket_beat_thread_loop ( void * data)
{
Tcp_Server * service = ( Tcp_Server * ) data;
while ( service-> m_run)
{
if ( service-> m_connectSockFd >= 0 )
{
std:: string beat = "action:heart beat" ;
send ( service-> m_connectSockFd, beat. c_str ( ) , beat. size ( ) , MSG_NOSIGNAL) ;
printf ( "send client:%s\n" , beat. c_str ( ) ) ;
}
sleep ( HEART_BEAT_INTERVAL) ;
}
return NULL ;
}
int Tcp_Server :: stop_tcp_server ( )
{
m_run = false ;
close ( m_connectSockFd) ;
close ( m_sockFd) ;
m_connectSockFd = - 1 ;
m_sockFd = - 1 ;
return 0 ;
}
int Tcp_Server :: start_tcp_server ( )
{
m_sockFd = socket ( AF_INET, SOCK_STREAM, 0 ) ;
if ( m_sockFd < 0 ) {
printf ( "create socket error: %s(errno: %d)\n" , strerror ( errno) , errno) ;
return - 1 ;
}
int optval = 1 ;
int ret = setsockopt ( m_sockFd, SOL_SOCKET, SO_REUSEADDR, & optval, sizeof ( optval) ) ;
if ( ret < 0 )
{
printf ( "Error setting socket option ret:%d\n" , ret) ;
return - 1 ;
}
struct sockaddr_in serverAddr;
memset ( & serverAddr, 0 , sizeof ( serverAddr) ) ;
serverAddr. sin_family = AF_INET;
serverAddr. sin_addr. s_addr = INADDR_ANY;
serverAddr. sin_port = htons ( TCP_PORT_NO) ;
if ( bind ( m_sockFd, ( struct sockaddr * ) & serverAddr, sizeof ( serverAddr) ) < 0 )
{
printf ( "Binding error: please try again in 20sec and make sure no other instance is running\n" ) ;
return - 1 ;
}
if ( - 1 == listen ( m_sockFd, 10 ) )
{
printf ( "listen socket error: %s(errno: %d)\n" , strerror ( errno) , errno) ;
return - 1 ;
}
printf ( "success to create tcp server...\n" ) ;
m_run = true ;
pthread_create ( & m_socketThread, NULL , tcp_socket_thread_loop, this ) ;
if ( ! m_socketThread) {
printf ( "create m_socketThread failed" ) ;
return - 1 ;
}
pthread_create ( & m_socketBeatThread, NULL , tcp_socket_beat_thread_loop, this ) ;
if ( ! m_socketBeatThread) {
printf ( "create m_socketBeatThread failed" ) ;
return - 1 ;
}
return 0 ;
}
Tcp_Server :: Tcp_Server ( )
{
m_run = false ;
m_sockFd = - 1 ;
m_connectSockFd = - 1 ;
}
Tcp_Server :: ~ Tcp_Server ( )
{
}
3.main.cpp源码
# include "tcp_server.h"
# include <unistd.h>
int main ( )
{
Tcp_Server :: get ( ) -> start_tcp_server ( ) ;
while ( 1 )
{
usleep ( 1000 ) ;
}
return 0 ;
}