CTcpServer类实现socket通讯多线程的服务端
#include "../_public.h"
CLogFile logfile;
CTcpServer TcpServer;
void EXIT(int sig);
pthread_spinlock_t vthidlock;
vector<pthread_t> vthid;
void *thmain(void *arg);
void thcleanup(void *arg);
int main(int argc,char *argv[])
{
if (argc!=3)
{
printf("Using:./demo20 port logfile\nExample:./demo20 5005 /tmp/demo20.log\n\n"); return -1;
}
CloseIOAndSignal(); signal(SIGINT,EXIT); signal(SIGTERM,EXIT);
if (logfile.Open(argv[2],"a+")==false) { printf("logfile.Open(%s) failed.\n",argv[2]); return -1; }
if (TcpServer.InitServer(atoi(argv[1]))==false)
{
logfile.Write("TcpServer.InitServer(%s) failed.\n",argv[1]); return -1;
}
pthread_spin_init(&vthidlock,0);
while (true)
{
if (TcpServer.Accept()==false)
{
logfile.Write("TcpServer.Accept() failed.\n"); EXIT(-1);
}
logfile.Write("客户端(%s)已连接。\n",TcpServer.GetIP());
pthread_t thid;
if (pthread_create(&thid,NULL,thmain,(void *)(long)TcpServer.m_connfd)!=0)
{
logfile.Write("pthread_create() failed.\n"); TcpServer.CloseListen(); continue;
}
pthread_spin_lock(&vthidlock);
vthid.push_back(thid);
pthread_spin_unlock(&vthidlock);
}
}
void *thmain(void *arg)
{
pthread_cleanup_push(thcleanup,arg);
int connfd=(int)(long)arg;
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL);
pthread_detach(pthread_self());
int ibuflen;
char buffer[102400];
while (1)
{
memset(buffer,0,sizeof(buffer));
if (TcpRead(connfd,buffer,&ibuflen,30)==false) break;
logfile.Write("接收:%s\n",buffer);
strcpy(buffer,"ok");
if (TcpWrite(connfd,buffer)==false) break;
logfile.Write("发送:%s\n",buffer);
}
close(connfd);
pthread_spin_lock(&vthidlock);
for (int ii=0;ii<vthid.size();ii++)
{
if (pthread_equal(pthread_self(),vthid[ii])) { vthid.erase(vthid.begin()+ii); break; }
}
pthread_spin_unlock(&vthidlock);
pthread_cleanup_pop(1);
}
void EXIT(int sig)
{
signal(SIGINT,SIG_IGN); signal(SIGTERM,SIG_IGN);
logfile.Write("进程退出,sig=%d。\n",sig);
TcpServer.CloseListen();
for (int ii=0;ii<vthid.size();ii++)
{
pthread_cancel(vthid[ii]);
}
sleep(1);
pthread_spin_destroy(&vthidlock);
exit(0);
}
void thcleanup(void *arg)
{
close((int)(long)arg);
logfile.Write("线程%lu退出。\n",pthread_self());
}
客户端
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
if (argc != 3)
{
printf("usage:./client ip port\n"); return -1;
}
int sockfd;
struct sockaddr_in servaddr;
char buf[1024];
if ((sockfd=socket(AF_INET,SOCK_STREAM,0))<0) { printf("socket() failed.\n"); return -1; }
memset(&servaddr,0,sizeof(servaddr));
servaddr.sin_family=AF_INET;
servaddr.sin_port=htons(atoi(argv[2]));
servaddr.sin_addr.s_addr=inet_addr(argv[1]);
if (connect(sockfd, (struct sockaddr *)&servaddr,sizeof(servaddr)) != 0)
{
printf("connect(%s:%s) failed.\n",argv[1],argv[2]); close(sockfd); return -1;
}
printf("connect ok.\n");
for (int ii=0;ii<5000000000;ii++)
{
memset(buf,0,sizeof(buf));
printf("please input:"); scanf("%s",buf);
if (send(sockfd,buf,strlen(buf),0) <=0)
{
printf("write() failed.\n"); close(sockfd); return -1;
}
memset(buf,0,sizeof(buf));
if (recv(sockfd,buf,sizeof(buf),0) <=0)
{
printf("read() failed.\n"); close(sockfd); return -1;
}
printf("recv:%s\n",buf);
}
}