client.cpp
#include
#include
#include
#include
#include
#include
#define SZ 10
using namespace std;
int main()
{
struct sockaddr_in remote_addr;
memset(&remote_addr,0,sizeof(remote_addr));
remote_addr.sin_family=AF_INET; //设置为IP通信
remote_addr.sin_addr.s_addr=inet_addr("127.0.0.1");//服务器IP地址
remote_addr.sin_port=htons(8000); //服务器端口号
//创建客户端套接字 IPv4 tcp
int client_sockfd=socket(AF_INET,SOCK_STREAM,0);
if(client_sockfd<0)
{
perror("socket error");
return 1;
}
//绑定服务器网络地址
if(connect(client_sockfd,(struct sockaddr*)&remote_addr,sizeof(remote_addr))<0)
{
perror("connect error");
return 1;
}
printf("connected to server sucessfully\n");
char buf[SZ]={0};
while(1)
{
printf("Enter string to send:");
scanf(" %s",buf);
if(!strcmp(buf,"quit")) break;
int len=send(client_sockfd,buf,strlen(buf),0);
len=recv(client_sockfd,buf,BUFSIZ,0);
buf[len]='\0';
printf("received:%s\n",buf);
}
close(client_sockfd);
return 0;
}
server.cpp
#include
#include
#include
#include
#include
#include
#define SZ 10
using namespace std;
int main()
{
struct sockaddr_in remote_addr;
memset(&remote_addr,0,sizeof(remote_addr));
remote_addr.sin_family=AF_INET; //设置为IP通信
remote_addr.sin_addr.s_addr=inet_addr("127.0.0.1");//服务器IP地址
remote_addr.sin_port=htons(8000); //服务器端口号
//创建客户端套接字 IPv4 tcp
int client_sockfd=socket(AF_INET,SOCK_STREAM,0);
if(client_sockfd<0)
{
perror("socket error");
return 1;
}
//绑定服务器网络地址
if(connect(client_sockfd,(struct sockaddr*)&remote_addr,sizeof(remote_addr))<0)
{
perror("connect error");
return 1;
}
printf("connected to server sucessfully\n");
char buf[SZ]={0};
while(1)
{
printf("Enter string to send:");
scanf(" %s",buf);
if(!strcmp(buf,"end")) break;
int len=send(client_sockfd,buf,strlen(buf),0);
len=recv(client_sockfd,buf,BUFSIZ,0);
buf[len]='\0';
printf("received:%s\n",buf);
}
close(client_sockfd);
return 0;
}
上述代码只允许服务器与一个客户端相连,如果有多个客户端就不能用这个服务器连接。
那么我们就可以利用多进程的知识去建立多个进程帮我们完成工作
server.cpp
#include
#include
#include
#include
#include
#include
#include
#include
#define SZ 10
using namespace std;
int crea_socket()
{
int listen_socket=socket(AF_INET,SOCK_STREAM,0);
if(listen_socket==-1)
{
perror("create socket error");
return -1;
}
sockaddr_in addr;
memset(&addr,0,sizeof(addr));
addr.sin_family=AF_INET;
addr.sin_port=htons(8000);
addr.sin_addr.s_addr=htonl(INADDR_ANY);
if((bind(listen_socket,(sockaddr*)&addr,sizeof(addr)))==-1)
{
perror("bind error");
return -1;
}
if((listen(listen_socket,5))==-1)
{
perror("listen error");
return -1;
}
return listen_socket;
}
int wait_client(int listen_socket)
{
sockaddr_in addr;
socklen_t sz=sizeof(addr);
printf("wait client to connect...\n");
int client_socket=accept(listen_socket,(sockaddr*)&addr,&sz);
if(client_socket==-1)
{
perror("accept error");
return -1;
}
printf("sucessful listen a client %s\n",inet_ntoa(addr.sin_addr));
return client_socket;
}
void hanld_client(int listen_socket,int client_socket)
{
char buf[SZ];
while(1)
{
int len=recv(client_socket,buf,SZ-1,0);
if(len<0)
{
perror("recv error");
break;
}
if(len==0) break;
buf[len]='\0';
printf("receive string:%s\n",buf);
send(client_socket,buf,len,0);
if(strncmp(buf,"end",3)==0) break;
}
close(client_socket);
}
void handler(int sig)
{
while(waitpid(-1,NULL,WNOHANG)>0)
{
printf("成功处理一个子进程");
}
}
int main()
{
int listen_sockfd=crea_socket();
signal(SIGCHLD,handler);
while(1)
{
int client_sockfd=wait_client(listen_sockfd);
int pid=fork();
if(pid==-1)
{
perror("fork error");
break;
}
if(pid>0)
{
close(client_sockfd);
continue;
}
if(pid==0)
{
close(listen_sockfd);
hanld_client(listen_sockfd,client_sockfd);
break;
}
}
close(listen_sockfd);
return 0;
}
利用终端运行两次client.cpp,得到结果如图
再次运行则会清理僵尸子进程
那么我们可以知道,多进程的花销某种程度上是很大的,能不能利用多线程帮助我们完成所需的操作呢。
多线程并发服务器
server.cpp
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define SZ 10
using namespace std;
int crea_socket()
{
int listen_socket=socket(AF_INET,SOCK_STREAM,0);
if(listen_socket==-1)
{
perror("create socket error");
return -1;
}
sockaddr_in addr;
memset(&addr,0,sizeof(addr));
addr.sin_family=AF_INET;
addr.sin_port=htons(8000);
addr.sin_addr.s_addr=htonl(INADDR_ANY);
if((bind(listen_socket,(sockaddr*)&addr,sizeof(addr)))==-1)
{
perror("bind error");
return -1;
}
if((listen(listen_socket,5))==-1)
{
perror("listen error");
return -1;
}
return listen_socket;
}
int wait_client(int listen_socket)
{
sockaddr_in addr;
socklen_t sz=sizeof(addr);
printf("wait client to connect...\n");
int client_socket=accept(listen_socket,(sockaddr*)&addr,&sz);
if(client_socket==-1)
{
perror("accept error");
return -1;
}
printf("sucessful listen a client %s\n",inet_ntoa(addr.sin_addr));
return client_socket;
}
void* hanld_client(void *client_sockfd)//参数为空指针
{
int client_socket=*((int*)client_sockfd);//先转换类型
char buf[SZ];
while(1)
{
int len=recv(client_socket,buf,SZ-1,0);
if(len<0)
{
perror("recv error");
break;
}
if(len==0) break;
buf[len]='\0';
printf("receive string:%s\n",buf);
send(client_socket,buf,len,0);
if(strncmp(buf,"end",3)==0) break;
}
close(client_socket);
pthread_exit(NULL);
}
int main()
{
int listen_sockfd=crea_socket();
while(1)
{
int client_sockfd=wait_client(listen_sockfd);
pthread_t id;
pthread_create(&id, NULL, hanld_client,&client_sockfd);//注意各个参数
pthread_detach(id);
}
close(listen_sockfd);
return 0;
}
利用多线程以及多进程的服务器并发暂时告一段落。。。
学无止境......