基于C客户端与多个服务器相连

对于看到很多人提出的基于C客户端与多个服务器相连的问题,我进行了具体的总结,附有源码,直接可以运行,不足之处还望大家指点!

这样的程序其实就是一个中间代理。

你可以把它想成:他就是一个拥有服务器的功能又有客户端的作用

难点在于充当客户端时怎么连接多个服务器----------------------------------------多线程的模式---------------------------几个服务器开启几个线程用于并行交互式传输数据

#include "px.h" 









/*
function:   Net_Read()
description:
            读通信数据
Input:
            date_fd:描述符
            chReadBuffer:需读入的缓冲区
            iSize:需读入的字节数
Output:
Return:     0:成功,other:不成功
others:
*/
int Net_Read(int date_fd, void *chReadBuffer, int iSize)
{
int iRcode;
int iHandle;
int iLeft;
char *pchBuffer;
iHandle = date_fd;
iLeft = iSize;
pchBuffer =(char *)chReadBuffer;
if(0 == iSize)
{
pchBuffer[0] = '\0';
return 0;
}


while(iLeft > 0)
{
iRcode = read(iHandle, pchBuffer, iLeft);
if(iRcode == 0)
{
printf("read wrong \n" );
return -1;
}
if(iRcode == -1)
{
if(errno == EINTR)
{
iRcode = 0;
}
else
{
return -1;
}
}
iLeft =iLeft - iRcode;
pchBuffer = pchBuffer + iRcode;


}
pchBuffer[iSize] = '\0';
return iSize;
}
/*
function:   Net_Write()
description:
            读通信数据
Input:
    date_fd :描述符
            chWriteBuffer:需写入的缓冲区
            iSize:写读入的字节数
Output:
Return:     0:成功,other:不成功
others:
*/
int Net_Write(int date_fd, const void *chWriteBuffer, int iSize)
{
int iRcode;
int iHandle;
int iLeft;
char *pchBuffer;
int len;
if(0 == iSize)
{
return 0;
}
iHandle = date_fd;
pchBuffer = (char *)chWriteBuffer;
iLeft = iSize;


while(iLeft > 0)
{
iRcode = write(iHandle, pchBuffer, iLeft);
if(iRcode == 0)
{
printf("Net_Write error\n");
return -1;
}
if(iRcode == -1)
{
if(errno == EINTR)
{
iRcode = 0;
}
else
{
return -1;
}
}


iLeft = iLeft - iRcode;
pchBuffer = pchBuffer + iRcode;
}


return iSize;
}
extern "C"
void * dealAcceptRecv(void * p)
{
stNet_AcceptNetInfo *AcceptNetInfo = (stNet_AcceptNetInfo *)p;
char buf[1024];
memset(buf,0,sizeof(buf));
int res;
int AcceptFd;
AcceptFd = AcceptNetInfo->iAcceptFd;
struct packetbody recvbufbody;
//struct packet recvbuf;
while(1)
{
memset(&recvbufbody, 0, sizeof(recvbufbody));
res = Net_Read(AcceptFd, &recvbufbody.recvbuf, 4);
if (res < 4)   //客户端关闭  
{  
printf("client close\n");  
break;  
}
res = Net_Read(AcceptFd, recvbufbody.bodybuf, recvbufbody.recvbuf.len);
//int len = atoi(recvbuf.lenbuf);

/*res = read(AcceptFd,buf,DATESIZE); 
if(res == 0)
{
printf("read wrong \n" );
return NULL;
}
if(res<0 && errno!=EAGAIN)
{
perror("read");
}*/
printf("read buf is -----%s\n",recvbufbody.bodybuf);
}  

/*while ( 1 )
{
res=read(AcceptFd,buf,DATESIZE);


if(res == 0)
{
printf("read wrong \n" );
return NULL;
}
if(res<0 && errno!=EAGAIN)
{
perror("read");
}
printf("read buf is -----%s\n",buf);
srand((int)time(0));
int index = (int)rand()%SER_ADDRNUM;
int nSize = readdateDeque[index].CAvector.size();
readdateDeque[index].CAvector.push_back(buf);
nSize = readdateDeque[index].CAvector.size();
} */
}
extern "C"
void * dealAcceptSend(void * p)
{
stNet_AcceptNetInfo *AcceptNetInfo = (stNet_AcceptNetInfo *)p;
char bufwrite[255];
memset(bufwrite,0,sizeof(bufwrite));
int res,nsize;
int AcceptFd;
AcceptFd = AcceptNetInfo->iAcceptFd;
int n = 0;
while(1)
{  
n++;
strcpy(bufwrite,"lijinqiu");
char tempsp[255];
memset(tempsp,0,sizeof(tempsp));
sprintf(tempsp,"%s%d号线程------第%05d个数据",bufwrite,threadNum,n);
res = send(AcceptFd,tempsp,34,0);


/*while ( 1 )
{
nsize = CAvectorFromServer.size();
for(int i = 0;i<nsize;i++)
{
strcpy(bufwrite,CAvectorFromServer[i]);
int bufSize = strlen(bufwrite);
res = write(AcceptFd,bufwrite,sizeof(bufSize));
       if(res == 0)
       {
           printf("Net_Write error\n");
           return NULL;
       }
       else if(res == -1)
       {
           if(errno == EINTR)
           {
               continue;
           }
           else
           {
               return NULL;
           }
       }
}
}*/
}
int RecAcceptStart(struct threadManager *threadinfo,stNet_AcceptNetInfo *AcceptNetInfo)
{
struct threadManager *pthreadinforec = threadinfo;
//初始化线程属性
pthread_attr_init(&pthreadinforec->attr);
int policy = sched_get_priority_max(SCHED_RR);
pthread_attr_setschedpolicy(&pthreadinforec->attr,policy);
pthread_attr_setschedparam(&pthreadinforec->attr,&param);
//do not inherit father's attr
pthread_attr_setinheritsched(&pthreadinforec->attr,PTHREAD_EXPLICIT_SCHED);
if( pthread_create(&pthreadinforec->pid,&pthreadinforec->attr,dealAcceptRecv,(void *)AcceptNetInfo) != 0 )
{
printf("pthread_create fail\n");
}
return 0;
}


int SendAcceptStart(struct threadManager *threadinfo,stNet_AcceptNetInfo *AcceptNetInfo)
{
struct threadManager *pthreadinfosend = threadinfo;
//初始化线程属性
pthread_attr_init(&pthreadinfosend->attr);
int policy = sched_get_priority_max(SCHED_RR);
pthread_attr_setschedpolicy(&pthreadinfosend->attr,policy);
pthread_attr_setschedparam(&pthreadinfosend->attr,&param);
//do not inherit father's attr
pthread_attr_setinheritsched(&pthreadinfosend->attr,PTHREAD_EXPLICIT_SCHED);
if( pthread_create(&pthreadinfosend->pid,&pthreadinfosend->attr,dealAcceptSend,(void *)AcceptNetInfo) != 0 )
{
printf("pthread_create fail\n");
}
return 0;
}
extern "C"
void * dealAccept(void * p)
{
char buf[255];
char bufwrite[255];


memset(buf,0,sizeof(buf));
memset(bufwrite,0,sizeof(bufwrite));
sockaddr_in srv, cli ;  
int listen_fd ,con_fd ;  
socklen_t  len;  
int res ,nsize,ws;  
int i;  
stNet_AcceptNetInfo Acceptgnetinfo;
bzero(&srv,sizeof(srv));  
bzero(&cli,sizeof(cli));  
srv.sin_port= SER_PORT ;  
srv.sin_family = AF_INET ;  
listen_fd = socket(AF_INET,SOCK_STREAM,0);  


int yes = 1;  
setsockopt(listen_fd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int));  


if(bind(listen_fd,(sockaddr*)&srv,sizeof(sockaddr))<0)  
{  
perror("bind");  
exit(0);  
}  
listen(listen_fd,100);  
while(1)
{
con_fd = accept(listen_fd,(sockaddr*)&cli ,&len);
if(con_fd < 0)
{
printf("accept is wrong\n");
break;
}
Acceptgnetinfo.listen_fd = listen_fd;
Acceptgnetinfo.iAcceptFd = con_fd;
RecAcceptStart(&g_threadInfo[threadNum],&Acceptgnetinfo);
threadNum++;
SendAcceptStart(&g_threadInfo[threadNum],&Acceptgnetinfo);
threadNum++;
/*if( pthread_create(&g_threadInfo[threadNum].pid,NULL,dealAcceptRecv,&Acceptgnetinfo) != 0 )
{
    printf("pthread_create dealRecv is fail\n");
}
threadNum++;
if( pthread_create(&g_threadInfo[threadNum].pid,NULL,dealAcceptSend,&Acceptgnetinfo) != 0 )
{
    printf("pthread_create dealSend is fail\n");
}
threadNum++;*/
}
}
extern "C"
void * dealConnectRecv(void * p)
{
stNet_ConnectNetInfo *ConnectNetInfo = (stNet_ConnectNetInfo *)p;
char bufwrite[255]; 
char buf[255];
memset(buf,0,sizeof(buf));
memset(bufwrite,0,sizeof(bufwrite));
int res,ws;
int con_fd;
con_fd = ConnectNetInfo->listen_fd;
int n = 0;
while(1)
{  
/*n++;
strcpy(bufwrite,"lijinqiu");
char tempsp[255];
sprintf(tempsp,"%s%d号线程------第%d个数据",bufwrite,threadNum,n);
ws = send(ConnectNetInfo->listen_fd,tempsp,sizeof(tempsp),0);
*/
//ws = send(listen_fd,buf,sizeof(buf),0);  


//printf("send buf is -----%s\n",tempsp);*/
res = read(con_fd,buf,sizeof(buf)); 
//res = recv(con_fd,buf,sizeof(buf),0); 
if(res == 0)
{
printf("read wrong \n" );
return NULL;
}
if(res<0 && errno!=EAGAIN)
{
perror("read");
}
printf("read buf is -----%s\n",buf);


/*int nSize = readdateDeque[threadIndex].CAvector.size();
for(int i = 0;i<nSize;i++)
{
strcpy(buf,readdateDeque[threadIndex].CAvector[i]);
strcpy(buf,"lijinqiu");
ws = send(con_fd,buf,sizeof(buf),0);  
char tempsp[255];
sprintf(tempsp,"%s%d",buf,threadIndex);
printf("send buf is -----%s\n",tempsp);
res = read(con_fd,writebuf,sizeof(writebuf)-1); 
printf("read buf is -----%s\n",writebuf);
//放入队列中返回给网元
CAvectorFromServer.push_back(writebuf);
}*/
}  


}
extern "C"
void * dealConnectSend(void * p)
{
stNet_ConnectNetInfo *ConnectNetInfo = (stNet_ConnectNetInfo *)p;
char bufwrite[255];
char buf[255];
memset(bufwrite,0,sizeof(bufwrite));
memset(buf,0,sizeof(buf));
int con_fd;
con_fd = ConnectNetInfo->listen_fd;
int res,nsize;
int n = 0;
while(1)
{  
n++;
strcpy(bufwrite,"lijinqiu");
char tempsp[255];
sprintf(tempsp,"%s%d号线程------第%d个数据",bufwrite,threadNum,n);
nsize = strlen(tempsp);
res = send(con_fd,tempsp,sizeof(tempsp),0);
//res = recv(con_fd,buf,sizeof(buf),0); 
//read(con_fd,buf,sizeof(buf)); 
//printf("read buf is -----%s\n",buf);
//printf("send buf is -----%s\n",tempsp);
/*res = read(con_fd,writebuf,sizeof(writebuf)); 
printf("read buf is -----%s\n",writebuf);*/


/*int nSize = readdateDeque[threadIndex].CAvector.size();
for(int i = 0;i<nSize;i++)
{
strcpy(buf,readdateDeque[threadIndex].CAvector[i]);
strcpy(buf,"lijinqiu");
ws = send(con_fd,buf,sizeof(buf),0);  
char tempsp[255];
sprintf(tempsp,"%s%d",buf,threadIndex);
printf("send buf is -----%s\n",tempsp);
res = read(con_fd,writebuf,sizeof(writebuf)-1); 
printf("read buf is -----%s\n",writebuf);
//放入队列中返回给网元
CAvectorFromServer.push_back(writebuf);
}*/
}  
}
int RecConnectStart(struct threadManager *threadinfo,stNet_ConnectNetInfo *ConnectNetInfo)
{
struct threadManager *pthreadinforec = threadinfo;
//初始化线程属性
pthread_attr_init(&pthreadinforec->attr);
int policy = sched_get_priority_max(SCHED_RR);
pthread_attr_setschedpolicy(&pthreadinforec->attr,policy);
pthread_attr_setschedparam(&pthreadinforec->attr,&param);
//do not inherit father's attr
pthread_attr_setinheritsched(&pthreadinforec->attr,PTHREAD_EXPLICIT_SCHED);
if( pthread_create(&pthreadinforec->pid,&pthreadinforec->attr,dealConnectRecv,(void *)ConnectNetInfo) != 0 )
{
printf("pthread_create fail\n");
}
return 0;
}


int SendConnectStart(struct threadManager *threadinfo,stNet_ConnectNetInfo *ConnectNetInfo)
{
struct threadManager *pthreadinfosend = threadinfo;
//初始化线程属性
pthread_attr_init(&pthreadinfosend->attr);
int policy = sched_get_priority_max(SCHED_RR);
pthread_attr_setschedpolicy(&pthreadinfosend->attr,policy);
pthread_attr_setschedparam(&pthreadinfosend->attr,&param);
//do not inherit father's attr
pthread_attr_setinheritsched(&pthreadinfosend->attr,PTHREAD_EXPLICIT_SCHED);
if( pthread_create(&pthreadinfosend->pid,&pthreadinfosend->attr,dealConnectSend,(void *)ConnectNetInfo) != 0 )
{
printf("pthread_create fail\n");
}
return 0;

}

作为客户端-------------------将要连接多个服务器

这里采用多线程的模式即---------------几个连接用几个线程

extern "C"
void * dealMoreConnect(void * p)
{
addrarry *addrarrynode =(addrarry*)p;
char buf[255];  
char writebuf[255];
int res,ws ;  
char addrarry[20];
memset(addrarry,0,sizeof(addrarry));
memset(buf,0,sizeof(buf));
memset(writebuf,0,sizeof(writebuf));
int listen_fd ;  
int threadIndex;
int nFdIndex = 0;
stNet_ConnectNetInfo Connectgnetinfo;
int isConnect = 0;
while(1)
{
if(isConnect == 0)
{
sockaddr_in srv, cli ;  
socklen_t  len;  
bzero(&srv,sizeof(srv));  
bzero(&cli,sizeof(cli));  
srv.sin_port= SER_PORT ;  
srv.sin_family = AF_INET ; 
//inet_pton(AF_INET,addrarrynode->addrarry_0,&srv.sin_addr); 
switch(addrarrynode->addrIndex)
{
case 0:
inet_pton(AF_INET,addrarrynode->addrarry_0,&srv.sin_addr); 
strcpy(addrarry,addrarrynode->addrarry_0);
threadIndex = 1;
break;
case 1:
inet_pton(AF_INET,addrarrynode->addrarry_1,&srv.sin_addr); 
strcpy(addrarry,addrarrynode->addrarry_1);
threadIndex = 2;
break;
case 2:
inet_pton(AF_INET,addrarrynode->addrarry_2,&srv.sin_addr); 
strcpy(addrarry,addrarrynode->addrarry_2);
threadIndex = 3;
break;
}

listen_fd = socket(AF_INET,SOCK_STREAM,0);  
if(connect(listen_fd,(sockaddr*)&srv,sizeof(sockaddr))<0)
{  
perror("connect is fail");
printf("connect  is fail-----------%s\n",addrarry);
close(listen_fd); 
break;  
}
isConnect = 1;
Connectgnetinfo.listen_fd = listen_fd;
RecConnectStart(&g_threadInfo[threadNum],&Connectgnetinfo);
threadNum++;
SendConnectStart(&g_threadInfo[threadNum],&Connectgnetinfo);
threadNum++;
/*if( pthread_create(&g_threadInfo[threadNum].pid,NULL,dealConnectRecv,&Connectgnetinfo) != 0 )
{
printf("pthread_create dealRecv is fail\n");
continue;  
}
threadNum++;
if( pthread_create(&g_threadInfo[threadNum].pid,NULL,dealConnectSend,&Connectgnetinfo) != 0 )
{
printf("pthread_create dealSend is fail\n");
continue;  
}
threadNum++;*/
printf("线程数--------[%d]\n",threadNum);
}
sleep(1);
}
}




int main(int argc,char**argv)
{   
addrarry addrarryNode;
memset(&addrarryNode,0,sizeof(addrarryNode));
strcpy(addrarryNode.addrarry_0,"172.21.10.32");
strcpy(addrarryNode.addrarry_1,"172.21.10.31");
strcpy(addrarryNode.addrarry_2,"172.21.10.30");
memset(&g_threadInfo,0,sizeof(g_threadInfo));
addrarryNode.addrIndex = 0;
/*for(int i = 0;i<3;i++)
       {
addrarryNode.addrIndex = i;
        if( pthread_create(&g_threadInfo[threadNum].pid,NULL,dealMoreConnect,(void*)&addrarryNode) != 0 )
{
        printf("pthread_create dealMoreConnect is fail\n");
continue;
    }
printf("dealMoreConnect--[%d]号线程开启\n",i+1);
threadNum++;
sleep(1);
}*/
if( pthread_create(&g_threadInfo[threadNum].pid,NULL,dealAccept,NULL) != 0 )
{
        printf("pthread_create dealAccept is fail\n");
    }
    threadNum++;


sleep(10);
printf("线程数--------[%d]\n",threadNum);
while(1)
{
sleep(1000);
}
return 0;

}  

px.h文件

#include <arpa/inet.h> 
#include <netinet/in.h>  
#include <sys/types.h>          /* See NOTES */  
#include <sys/socket.h>  
#include <string.h>  
#include <stdio.h>  
#include <unistd.h>  
#include <pthread.h>  
#include <errno.h>  
#include <stdlib.h> 
#include <vector> 


using std::vector;
typedef struct sockaddr_in sockaddr_in ;  
typedef struct sockaddr     sockaddr ;  
#define DATESIZE    28
#define THREADMAXNUM    10
#define SER_ADDRNUM    3 
#define SER_PORT    8080 
#define IP_ADDR1     "172.21.10.32"
#define IP_ADDR2     "172.21.10.31"
#define IP_ADDR3     "172.21.10.30"
typedef struct
{
  char addrarry_0[20];
char addrarry_1[20];
char addrarry_2[20];
int addrIndex;

}addrarry;  
typedef struct
{
vector<char*> CAvector;
}readDeque;
/*typedef struct
{
vector<char*> CAvector;
}readDequeFromServer;
readDequeFromServer readDateDequeFromServer;*/
readDeque readdateDeque[SER_ADDRNUM];


//char *addrarry[3];
int threadNum = 0;
struct threadManager
{
pthread_t pid;
pthread_attr_t    attr;
};
struct sched_param param;
struct threadManager  g_threadInfo[THREADMAXNUM];
//pthread_t pid[THREADMAXNUM];
vector<char*> CAvectorFromServer;
/*网络通讯共用结构体*/
typedef struct
{
int listen_fd;
int iAcceptFd;
//struct sockaddr_in stSocketAddress;


}stNet_AcceptNetInfo;
/*网络通讯共用结构体*/
typedef struct
{
int listen_fd;
//int iAcceptFd;
//struct sockaddr_in stSocketAddress;


}stNet_ConnectNetInfo;
//stNet_AcceptNetInfo gnetinfo;
//stNet_ConnectNetInfo Connectgnetinfo;
/*
struct packet { 
    char lenbuf[5];  
    char buf[1024];  
}; */
struct packet { 
int len;
}; 
struct packetbody { 
struct packet recvbuf;
char bodybuf[1024];
}; 
int Net_Write(int date_fd,const void *chWriteBuffer, int iSize);
int Net_Read(int date_fd, void *chReadBuffer, int iSize);
int SendConnectStart(struct threadManager *threadinfo,stNet_ConnectNetInfo *ConnectNetInfo);
int RecConnectStart(struct threadManager *threadinfo,stNet_ConnectNetInfo *ConnectNetInfo);
int SendAcceptStart(struct threadManager *threadinfo,stNet_AcceptNetInfo *AcceptNetInfo);
int RecAcceptStart(struct threadManager *threadinfo,stNet_AcceptNetInfo *AcceptNetInfo);


class cStartThread
{
public:
cStartThread();
virtual ~cStartThread();
int RecAcceptStart(struct threadManager *threadinfo,stNet_AcceptNetInfo *AcceptNetInfo);
int SendAcceptStart(struct threadManager *threadinfo,stNet_AcceptNetInfo *AcceptNetInfo);
int RecConnectStart(struct threadManager *threadinfo,stNet_ConnectNetInfo *ConnectNetInfo);
int SendConnectStart(struct threadManager *threadinfo,stNet_ConnectNetInfo *ConnectNetInfo);
int dealDateStart(struct threadManager *threadinfo,stNet_ConnectNetInfo *ConnectNetInfo);


//stNet_NetInfo netinfo;


struct threadManager *pthreadAcceptinforec;
struct threadManager *pthreadAcceptinfosend;
struct threadManager *pthreadConnectinforec;
struct threadManager *pthreadConnectinfosend;


};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值