简单的socket服务器端和客户端程序,实现但server多client连接
只作参考作用,比较初级
server代码:
#include"socket.h"
///////////////////////////////////////////////////////////////////////////////////
tcpserver::tcpserver()
{
MaxFD = -1;
server_sock_fd = -1;
backlog = 4; //完成三次握手但没有accept的队列的长度
UsrPara.tv.tv_sec = 5;
UsrPara.tv.tv_usec = 0;
UsrPara.ip = "127.0.0.1";
UsrPara.port = 11345;
UsrPara.MaxConnect = 10; //应用层同时可以处理的连接
UsrPara.BuffSize = 1024;
UsrPara.CmdQuit = "stop";
}
///////////////////////////////////////////////////////////////////////////////////
tcpserver::~tcpserver()
{
delete[](send_msg);
delete[](recv_msg);
delete[](client_fd_arr);
}
///////////////////////////////////////////////////////////////////////////////////
bool tcpserver::LoadPara(serverpara U_P)
{
if(!((U_P.tv.tv_sec == 0)&&(U_P.tv.tv_usec == 0))){UsrPara.tv.tv_sec = U_P.tv.tv_sec;UsrPara.tv.tv_usec = U_P.tv.tv_usec;}
if(0 != U_P.ip.compare("")){UsrPara.ip = U_P.ip;}
if(0 != U_P.port){UsrPara.port = U_P.port;}
if(0 != U_P.MaxConnect){UsrPara.MaxConnect = U_P.MaxConnect;}
if(0 != U_P.BuffSize){UsrPara.BuffSize = U_P.BuffSize;}
if(0 != U_P.CmdQuit.compare("")){UsrPara.CmdQuit = U_P.CmdQuit;}
send_msg = new char[UsrPara.BuffSize];
recv_msg = new char[UsrPara.BuffSize];
client_fd_arr = new int[UsrPara.BuffSize];
return 1;
}
///////////////////////////////////////////////////////////////////////////////////
bool tcpserver::CreateLink()
{
//本地地址
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(UsrPara.port);
server_addr.sin_addr.s_addr = inet_addr(UsrPara.ip.c_str());
bzero(&(server_addr.sin_zero), 8);
//创建socket
server_sock_fd = socket(AF_INET, SOCK_STREAM, 0);
if(server_sock_fd == -1){ printf("socket error");return false;}
//绑定socket
int bind_result = bind(server_sock_fd, (struct sockaddr *)&server_addr, sizeof(server_addr));
if(bind_result == -1){printf("bind error");return false;}
//listen
if(listen(server_sock_fd, backlog) == -1){printf("listen error");return false;}
return true;
}
///////////////////////////////////////////////////////////////////////////////////
int tcpserver::SetMonitor()
{
struct timeval OutTime;
OutTime.tv_sec = UsrPara.tv.tv_sec;
OutTime.tv_usec = UsrPara.tv.tv_usec;
FD_ZERO(&server_fd_set);
FD_SET(STDIN_FILENO, &server_fd_set);
if(MaxFD
FD_SET(server_sock_fd, &server_fd_set);
if(MaxFD < server_sock_fd){MaxFD = server_sock_fd;}
//客户端连接
for(int i =0; i < UsrPara.MaxConnect; i++)
{
if(client_fd_arr[i] != 0)
{
FD_SET(client_fd_arr[i], &server_fd_set);
if(MaxFD < client_fd_arr[i]){MaxFD = client_fd_arr[i];}
}
}
int ret = select(MaxFD + 1, &server_fd_set, NULL, NULL, &OutTime);
if(ret < 0){printf("ERR : tcp server select error\n");return ret;}
// else if(ret == 0){printf("ERR : tcp server select overtime\n");return 0;}
return 1;
}
///////////////////////////////////////////////////////////////////////////////////
int tcpserver::DealMonitor()
{
//有新的输入
if(FD_ISSET(STDIN_FILENO, &server_fd_set))
{
printf("发送消息:%s\n",send_msg);
bzero(send_msg, UsrPara.BuffSize);
fgets(send_msg, UsrPara.BuffSize, stdin);
string mid(send_msg,UsrPara.CmdQuit.size());
//输入“stop"则退出服务器
if(0 == mid.compare(UsrPara.CmdQuit)){return -1;}
for(int i = 0; i < UsrPara.MaxConnect; i++)
{
if(client_fd_arr[i] != 0){printf("client_fd_arr[%d]=%d\n", i, client_fd_arr[i]);send(client_fd_arr[i], send_msg, UsrPara.BuffSize, 0);}
}
}
//有新的连接请求
if(FD_ISSET(server_sock_fd, &server_fd_set))
{
struct sockaddr_in client_address;
socklen_t address_len;
int client_sock_fd = accept(server_sock_fd, (struct sockaddr *)&client_address, &address_len);
printf("提示 : new connection client_sock_fd = %d\n", client_sock_fd);
if(client_sock_fd > 0)
{
int index = -1;
for(int i = 0; i < UsrPara.MaxConnect; i++)
{
if(client_fd_arr[i] == 0){index = i;client_fd_arr[i] = client_sock_fd;return 0;}
}
if(index >= 0)
{printf("提示 : 新客户端(%d)加入成功 %s:%d\n", index, inet_ntoa(client_address.sin_addr), ntohs(client_address.sin_port));}
else
{
bzero(send_msg, UsrPara.BuffSize);
strcpy(send_msg, "提示 : 服务器加入的客户端数达到最大值,无法加入!\n");
send(client_sock_fd, send_msg, UsrPara.BuffSize, 0);
printf("提示 : 客户端连接数达到最大值,新客户端加入失败 %s:%d\n", inet_ntoa(client_address.sin_addr), ntohs(client_address.sin_port));
}
}
}
for(int i =0; i < UsrPara.MaxConnect; i++)
{
if(client_fd_arr[i] !=0)
{
if(FD_ISSET(client_fd_arr[i], &server_fd_set))
{
//处理某个客户端过来的消息
bzero(recv_msg, UsrPara.BuffSize);
long byte_num = recv(client_fd_arr[i], recv_msg, UsrPara.BuffSize, 0);
if (byte_num > 0)
{
if(byte_num > UsrPara.BuffSize){byte_num = UsrPara.BuffSize;}
recv_msg[byte_num] = '\0';
printf("提示 : 客户端(%d):%s\n", i, recv_msg);
}
else if(byte_num < 0){printf("提示 : 从客户端(%d)接受消息出错.\n", i);}
else
{
FD_CLR(client_fd_arr[i], &server_fd_set);
client_fd_arr[i] = 0;
printf("提示 : 客户端(%d)退出了\n", i);
}
}
}
}
return 1;
}
///////////////////////////////////////////////////////////////////////////////////
void tcpserver::RUN()
{
long int MidTime=0,ContrastTime=0;
int SetRet=0,DealRet=0;state = 0;
int nowtime[8] = {0};
if(!CreateLink()){printf("***tcp server run fail***\n");return;}
while(state == 0)
{
SetRet = SetMonitor();
if(SetRet<0){printf("***tcp server run fail***\n");break;}
else if(SetRet>0);
{
DealRet = DealMonitor();
if(DealRet == -1){printf("提示 : ***manual shut down tcp server service***\n");break;}
}
MidTime = NowTime(nowtime);
if(MidTime-ContrastTime>4)
{
ContrastTime = MidTime;
printf("%d-%02d-%02d %02d:%02d:%02d : 提示 : tcp server running ...\n",nowtime[0],nowtime[1],nowtime[2],nowtime[3],nowtime[4],nowtime[5]);
}
}
return;
}
///////////////////////////////////////////////////////////////////////////////////
void tcpserver::STOP()
{
state = 1;
printf("提示 : ***auto shut down server service***\n");
}
///////////////////////////////////////////////////////////////////////////////////
long int tcpserver::NowTime(int *dest)
{
long int RET;
time_t nowtime;
struct timeval tv;
gettimeofday(&tv,NULL);
RET = tv.tv_sec;
// RET = tv.tv_sec * 1000 + tv.tv_usec / 1000;
time(&nowtime);
tm* t= localtime(&nowtime);
dest[0] = t->tm_year + 1900;
dest[1] = t->tm_mon + 1;
dest[2] = t->tm_mday;
dest[3] = t->tm_hour;
dest[4] = t->tm_min;
dest[5] = t->tm_sec;
return RET;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
server主函数调用部分:
#include
#include "socket.h"
int main(int argc, char **argv) {
serverpara PARAOBJ;
tcpserver OBJ;
OBJ.LoadPara(PARAOBJ);
OBJ.RUN();
return 0;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
client代码:
#include"tcpclient.h"
tcpclient::tcpclient()
{
server_sock_fd = -1;
UsrPara.tv.tv_sec = 5;
UsrPara.tv.tv_usec = 0;
UsrPara.ip = "127.0.0.1";
UsrPara.port = 11345;
UsrPara.MaxConnect = 10; //应用层同时可以处理的连接
UsrPara.BuffSize = 1024;
UsrPara.CmdQuit = "stop";
}
///////////////////////////////////////////////////////////////////////////////////
tcpclient::~tcpclient()
{
delete[](send_msg);
delete[](recv_msg);
}
///////////////////////////////////////////////////////////////////////////////////
bool tcpclient::ClientLoadPara(clientpara U_P)
{
if(!((U_P.tv.tv_sec == 0)&&(U_P.tv.tv_usec == 0))){UsrPara.tv.tv_sec = U_P.tv.tv_sec;UsrPara.tv.tv_usec = U_P.tv.tv_usec;}
if(0 != U_P.ip.compare("")){UsrPara.ip = U_P.ip;}
if(0 != U_P.port){UsrPara.port = U_P.port;}
if(0 != U_P.MaxConnect){UsrPara.MaxConnect = U_P.MaxConnect;}
if(0 != U_P.BuffSize){UsrPara.BuffSize = U_P.BuffSize;}
if(0 != U_P.CmdQuit.compare("")){UsrPara.CmdQuit = U_P.CmdQuit;}
send_msg = new char[UsrPara.BuffSize];
recv_msg = new char[UsrPara.BuffSize];
return 1;
}
///////////////////////////////////////////////////////////////////////////////////
bool tcpclient::ClientCreateLink()
{
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(UsrPara.port);
server_addr.sin_addr.s_addr = inet_addr(UsrPara.ip.c_str());
bzero(&(server_addr.sin_zero), 8);
//创建socket
server_sock_fd = socket(AF_INET, SOCK_STREAM, 0);
if(server_sock_fd == -1){ printf("client socket error");return false;}
if(connect(server_sock_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr_in)) == 0)
return true;
}
///////////////////////////////////////////////////////////////////////////////////
int tcpclient::ClientSetMonitor()
{
struct timeval OverTime;
OverTime.tv_sec = UsrPara.tv.tv_sec;
OverTime.tv_usec = UsrPara.tv.tv_usec;
FD_ZERO(&client_fd_set);
FD_SET(STDIN_FILENO, &client_fd_set);
FD_SET(server_sock_fd, &client_fd_set);
int ret = select(server_sock_fd + 1, &client_fd_set, NULL, NULL, &OverTime);
if(ret < 0){printf("ERR : tcp client select error\n");return ret;}
// else if(ret == 0){printf("ERR : tcp client select overtime\n");return 0;}
return 1;
}
///////////////////////////////////////////////////////////////////////////////////
int tcpclient::ClientDealMonitor()
{
if(FD_ISSET(STDIN_FILENO, &client_fd_set))
{
bzero(send_msg, UsrPara.BuffSize);
fgets(send_msg, UsrPara.BuffSize, stdin);
string mid(send_msg,UsrPara.CmdQuit.size());
//输入“stop"则退出服务器
if(0 == mid.compare(UsrPara.CmdQuit)){return -1;}
if(send(server_sock_fd, send_msg, UsrPara.BuffSize, 0) == -1){printf("提示 : 发送消息失败!\n");}
}
if(FD_ISSET(server_sock_fd, &client_fd_set))
{
bzero(recv_msg, UsrPara.BuffSize);
long byte_num = recv(server_sock_fd, recv_msg, UsrPara.BuffSize, 0);
if(byte_num > 0)
{
if(byte_num > UsrPara.BuffSize){byte_num = UsrPara.BuffSize;}
recv_msg[byte_num] = '\0';
printf("提示 : 服务器的应答:%s\n", recv_msg);
}
else if(byte_num < 0){printf("接受消息失败!\n");return -2;}
else{printf("提示 : 服务器未运行!\n");return -3;}
}
}
///////////////////////////////////////////////////////////////////////////////////
void tcpclient::CLIENTRUN()
{
long int MidTime=0,ContrastTime=0;
int SetRet=0,DealRet=0;state = 0;
int nowtime[8] = {0};
if(!ClientCreateLink()){printf("***tcp client run fail***\n");return;}
while(state == 0)
{
SetRet = ClientSetMonitor();
if(SetRet<0){printf("***tcp client run fail***\n");break;}
// else if(state == 0){printf("***communication timeout***\n");}
else if(SetRet>0);
{
DealRet = ClientDealMonitor();
if(DealRet == -1){printf("提示 : ***manual shut down tcp server service***\n");break;}
if(DealRet == -3){printf("提示 : ***passive turn off this client***\n");break;}
}
MidTime = NowTime(nowtime);
if(MidTime-ContrastTime>4)
{
ContrastTime = MidTime;
printf("%d-%02d-%02d %02d:%02d:%02d : 提示 : tcp client running ...\n",nowtime[0],nowtime[1],nowtime[2],nowtime[3],nowtime[4],nowtime[5]);
}
}
return;
}
///////////////////////////////////////////////////////////////////////////////////
void tcpclient::CLIENTSTOP()
{
state = 1;
printf("提示 : ***auto shut down server service***\n");
return;
}
///////////////////////////////////////////////////////////////////////////////////
long int tcpclient::NowTime(int *dest)
{
long int RET;
time_t nowtime;
struct timeval tv;
gettimeofday(&tv,NULL);
RET = tv.tv_sec;
// RET = tv.tv_sec * 1000 + tv.tv_usec / 1000;
time(&nowtime);
tm* t= localtime(&nowtime);
dest[0] = t->tm_year + 1900;
dest[1] = t->tm_mon + 1;
dest[2] = t->tm_mday;
dest[3] = t->tm_hour;
dest[4] = t->tm_min;
dest[5] = t->tm_sec;
return RET;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
client主函数调用部分:
#include
#include "tcpclient.h"
int main(int argc, char **argv){
clientpara PARA;
tcpclient OBJ;
OBJ.ClientLoadPara(PARA);
OBJ.CLIENTRUN();
return 0;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
小提示:select函数超时设置,和被监控的套接字文件在调用select函数后会被清除,所以循环select函数之前必须重新载入超时时间和被监控的套接字,否则select会超时。