这篇博客介绍多线程并发服务器的实现。
下面贴代码。
服务端代码
#include<stdio.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<string.h>
#include<errno.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<iostream>
#include<pthread.h>
using namespace std;
#define SERVERIP "127.0.0.1"
#define SERVERPORT 12345
#define MAXBUFFER 256
pthread_t ntid;//线程
int connfd;//客户端连接的ID
struct sockaddr_in clientaddr;
void *printContext(void *arg)
{
char ip[40]={0};//用来存放客户端连接的IP地址
char readBuf[MAXBUFFER]={0};
int ret;
pthread_detach(ntid);//线程退出时,可以清理内存
int pconnfd=connfd;//客户端连接的ID(main函数中的accept的返回值)
//线程自己要保存连接符 ID,因为进程在第二个客户端
//连接后,会覆盖connfd
printf("%s\n",inet_ntop(AF_INET,&clientaddr.sin_addr,ip,sizeof(ip)));
cout<<"connectd to the server"<<endl;
while(ret=read(pconnfd,readBuf,MAXBUFFER))//读客户端发送的数据
{
write(pconnfd,readBuf,MAXBUFFER);//写回客户端
printf("%s\n",readBuf);//打印传输的内容
bzero(readBuf,MAXBUFFER);
}
if(ret==0)
{
printf("the connection of client is close!\n");
}else
{
printf("read error:%s\n",strerror(errno));
}
pthread_exit(0);
}
int main(int argc,char** argv)
{
socklen_t len;//socket长度类型
int serverFd,ret;
struct sockaddr_in serveraddr;
serverFd=socket(AF_INET,SOCK_STREAM,0);//创建socket
if(serverFd<0)
{
printf("socket error:%s\n",strerror(errno));
exit(-1);
}
bzero(&serveraddr,sizeof(serveraddr));//serveraddr清零
serveraddr.sin_family=AF_INET;
serveraddr.sin_port=htons(SERVERPORT);
inet_pton(AF_INET,SERVERIP,&serveraddr.sin_addr);//将C语言字节序转化成网络字节序
ret=bind(serverFd,(struct sockaddr *)&serveraddr,sizeof(serveraddr));
if(ret!=0)
{
close(serverFd);
printf("bind error:%\n",strerror(errno));
exit(-1);
}
ret=listen(serverFd,5);//监听
if(ret!=0)
{
close(serverFd);
printf("listen error:%s\n",strerror(errno));
exit(-1);
}
//clientaddr清零
len=sizeof(clientaddr);
bzero(&clientaddr,sizeof(clientaddr));
while(1)
{
//接收客户端的连接,然后启动线程去处理客户端发送的
//请求。线程只要保存connfd 即可。进程在第二个客户 端
//连接进来的时候,会覆盖第一个客户端的connfd
connfd=accept(serverFd,(struct sockaddr *) &clientaddr,&len);
if(connfd<0)
{
printf("accept error:%s\n",strerror(errno));
continue;
}
int err;
err=pthread_create(&ntid,NULL,printContext,NULL);
if(err!=0)
{
cout<<"can't create pthread"<<endl;
}
//close(connfd);
}
close(serverFd);
return 0;
}
客户端代码
#include<stdio.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<string.h>
#include<errno.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#define SERVERIP "127.0.0.1"
#define SERVERPORT 12345
#define MAXBUFFER 256
int main(int argc,char** argv)
{
int clientFd,ret;
struct sockaddr_in serveraddr;
char buf[MAXBUFFER];
clientFd=socket(AF_INET,SOCK_STREAM,0);//创建socket
if(clientFd<0)
{
printf("socket error:%s \n",strerror(errno));
exit(-1);
}
bzero(&serveraddr,sizeof(serveraddr));
serveraddr.sin_family=AF_INET;
serveraddr.sin_port=htons(SERVERPORT);
inet_pton(AF_INET,SERVERIP,&serveraddr.sin_addr);
//连接到服务器
ret=connect(clientFd,(struct sockaddr *)&serveraddr,sizeof(serveraddr));
if(ret!=0)
{
close(clientFd);
printf("connect error:%s \n",strerror(errno));
exit(-1);
}
while(1)
{
bzero(buf,sizeof(buf));
scanf("%s",buf);
write(clientFd,buf,sizeof(buf));//写数据
bzero(buf,sizeof(buf));
read(clientFd,buf,sizeof(buf));//读数据
printf("echo:%s\n",buf);
}
close(clientFd);
return (EXIT_SUCCESS);
}
服务端在编译时要加上“-lpthread”。