如何实现多个客户端连接,服务器有相应。
服务器是只有一个线程,主线程
1、能够监听客户端的连接请求;
2、能够接收已经连接的客户端发送来的数据。
3、已经连接的客户端发送某个数据,回复相同数据给它。
|
sfd
new_fd1,...
select
fd_set tmpset
客户端不断开,不停的输入话语,发送给服务器端
1、服务器端和客户端进行即时聊天,一个服务器端,一个客户端。
|
tcp_server_s.c | tcp_client_s.c |
#include"func.h"
#define NUM 10
int main(int argc,char** argv)
{
if(argc!=3)
{
printf("error args\n");
return -1;
}
int sfd=socket(AF_INET,SOCK_STREAM,0);
if(-1==sfd)
{
perror("socket");
return -1;
}
struct sockaddr_in ser;
memset(&ser,0,sizeof(ser));
ser.sin_family=AF_INET;
ser.sin_port=htons(atoi(argv[2]));
ser.sin_addr.s_addr=inet_addr(argv[1]);
int ret;
ret=bind(sfd,(struct sockaddr*)&ser,sizeof(struct sockaddr));
if(-1==ret)
{
perror("bind");
return -1;
}
ret=listen(sfd,NUM);
if(-1==ret)
{
perror("listen");
return -1;
}
printf("listen success\n");
struct sockaddr_in client;
memset(&client,0,sizeof(client));
int addrlen=sizeof(struct sockaddr);
fd_set rdset;
int new_fd[NUM]={0};
int i=0;
int j;
fd_set tmpset;
FD_ZERO(&tmpset);
FD_SET(sfd,&tmpset);
char buf[128]={0};
while(1)
{
FD_ZERO(&rdset);
memcpy(&rdset,&tmpset,sizeof(rdset));
ret=select(NUM+4,&rdset,NULL,NULL,NULL);
if(ret>0)
{
if(FD_ISSET(sfd,&rdset))
{
new_fd[i]=accept(sfd,(struct sockaddr*)&client,&addrlen);
if(-1==new_fd[i])
{
perror("accept");
return -1;
}
printf("client ip = %s port = %d\n",inet_ntoa(client.sin_addr),nto hs(client.sin_port));
FD_SET(new_fd[i],&tmpset);
i++;
}
j=0;
while(new_fd[j]!=0)
{
if(FD_ISSET(new_fd[j],&rdset))
{
memset(buf,0,sizeof(buf));
ret=recv(new_fd[j],buf,sizeof(buf),0);
if(ret>0)
{
printf("newfd %d recv buf =%s\n",newfd[j],buf);
ret=send(new_fd[j],buf,strlen(buf),0);
if(ret==-1)
{
perror("send");
return -1;
}
else if(ret==0) //客户端断开和管道一样,读到0,服务器这边会一直显示打印0,所以要关闭;
{
printf("close client ip = %s port = %d\n",inet_ntoa(client .sin_addr),ntohs(client.sin_port));
close(new_fd[j]);
FD_CLR(new_fd[j],&tmpset);
}
}
}
j++;
}
}
}
return 0;
}
|
#include"func.h"
int main(int argc,char** argv)
{
if(argc!=3)
{
printf("error args\n");
return -1;
}
int sfd=socket(AF_INET,SOCK_STREAM,0);
if(-1==sfd)
{
perror("socket");
return -1;
}
struct sockaddr_in ser;
memset(&ser,0,sizeof(ser));
ser.sin_family=AF_INET;
ser.sin_port=htons(atoi(argv[2]));
ser.sin_addr.s_addr=inet_addr(argv[1]);
int ret;
ret=connect(sfd,(struct sockaddr*)&ser,sizeof(struct sockaddr));
if(-1==ret)
{
perror("connect");
return -1;
}
char buf[128]={0};
while(1)
{
memset(buf,0,sizeof(buf));
ret=read(0,buf,sizeof(buf));
if(ret<=0)
{
break;
}
ret=send(sfd,buf,strlen(buf)-1,0);
if(-1==ret)
{
perror("send");
return -1;
}
memset(buf,0,sizeof(buf));
ret=recv(sfd,buf,sizeof(buf),0);
if(-1==ret)
{
perror("recv");
return -1;
}
printf("recv from server:%s\n",buf);
}
return 0;
}
|
func.h | Makefile |
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/select.h>
|
tcp_server_s:tcp_server_s.c tcp_client_s.c gcc tcp_server_s.c -o tcp_server_s gcc tcp_client_s.c -o tcp_client_s .PHONY:clean clean: rm tcp_server_s tcp_client_s |