1. 程式人生 > >Linux C網路程式設計 ————6、IO複用併發伺服器程式設計

Linux C網路程式設計 ————6、IO複用併發伺服器程式設計

伺服器端程式碼實現

#include<stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/time.h>

#define PORT 1234
#define BACKLOG 5
#define MAXDATASIZE 1000

typedef struct 
{
	int fd;
	char *name;
	struct sockaddr_in addr;
	char *data;
}CLIENT;

void process_cli(CLIENT *client,char * recvbuf,int len);
void savedata(char *recvbuf,int len,char data);

main()
{
	int i ,maxi,maxfd,sockfd;
	int nready;
	ssize_t n;
	fd_set rset,allset;
	int listenfd,connectfd;
	struct sockaddr_in server;
	
	CLIENT client[FD_SETSIZE];
	char recvbuf[MAXDATASIZE];
	int sin_size;
	
	if((listenfd=socket(AF_INET,SOCK_STREAM,0))==-1)
	{
		perror("Creating socket failed.");
		exit(1);
	}
	int opt=SO_REUSEADDR;
	setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
	
	bzero(&server,sizeof(server));
	server.sin_family=AF_INET;
	server.sin_port=htons(PORT);
	server.sin_addr.s_addr=htonl(INADDR_ANY);
	if(bind(listenfd,(struct sockaddr *)&server,sizeof(struct sockaddr))==-1)
	{
		perror("Bind error.");
		exit(1);
	}
	if(listen(listenfd,BACKLOG)==-1)
	{
		perror("listen() error\n");
		exit(1);
	}
	
	sin_size=sizeof(struct sockaddr_in);
	maxfd=listenfd;
	maxi=-1;
	for(i=0;i<FD_SETSIZE;i++)
	{
		client[i].fd=-1;
	}
	FD_ZERO(&allset);
	FD_SET(listenfd,&allset);
	
	while(1)
	{
		struct sockaddr_in addr;
		rset=allset;
		nready=select(maxfd+1,&rset,NULL,NULL,NULL);
		
		if(FD_ISSET(listenfd,&rset))
		{
			if((connectfd=accept(listenfd,(struct sockaddr *)&addr,&sin_size))==-1)
			{
				perror("accept() error");
				continue;
			}
			
			for(i=0;i<FD_SETSIZE;i++)	
				if(client[i].fd<0)
				{
					client[i].fd=connectfd;
					client[i].name=malloc(char[MAXDATASIZE]);
					client[i].addr=addr;
					client[i].data=malloc(char[MAXDATASIZE]);
					client[i].name[0]='\0';
					client[i].data[0]='\0';
					printf("You got a connection from %s",inet_ntoa(client[i].addr.sin_addr));
					break;
				}
				if(i==FD_SETSIZE)
					FD_SET(connectfd,&allset);
				if(connectfd>maxfd)
					maxfd=connectfd;
				if(i>maxi)
					maxi=i;
				if(--nready<=0)
					continue;
		}
		for(i=0;i<=maxi;i++)
		{
			if((sockfd=client[i].fd)<0)
				continue;
			if(FD_ISSET(sockfd,&rset))
			{
				if((n=recv(sockfd,recvbuf,MAXDATASIZE,0))==0)
				{
					close(sockfd);
					printf("Client(%s) closed connection.User's data:%s\n",client[i].name,client[i].data);
					FD_CLR(sockfd,&allset);
					client[i].fd=-1;
					free(client[i].name);
					free(client[i].data);
				}
				else
					process_cli(&client[i],recvbuf,n);
				if(--nready<=0)
					break;
			}
		}
		
	}
	close(listenfd);
	
}
	
void process_cli(CLIENT * client,char * recvbuf,int len)
{
	char sendbuf[MAXDATASIZE];
	recvbuf[len-1]='\0';
	if(strlen(client->name)==0)
	{
		memcpy(client->name,recvbuf,len);
		printf("Client's name is %s.\n",client->name);
		return;
	}
	printf("Received client(%s) message:%s\n",client->name,recvbuf);
	savedata(recvbuf,len,client->data);
	for(int il=0;il<len-1;il++)
	{
		sendbuf[il]=recvbuf[len-il-2];
	}
	sendbuf[len-1]='\0';

	send(client->fd,sendbuf,strlen(sendbuf),0);
}

void savedata(char *recvbuf,int len,char *data)
{
	int start =strlen(data);
	for(int i=0;i<len;i++)
	{
		data[start+i]=recvbuf[i];
	}
}

客戶端程式碼實現

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define PORT 1234
#define MAXDATASIZE 100
void process(FILE *fp,int sockfd);
char* getMessage(char* sendline,int len,FILE* fp);
int main(int argc,char *argv[]){
	int sockfd;
	struct  hostent *he;
	struct sockaddr_in server;
	if (argc!=2){
		printf("Usage:%s<IP Address>\n",argv[0]);
		exit(1);
	}
	if((he=gethostbyname(argv[1]))==NULL){
		printf("gethostbyname() error\n");
		exit(1);
	}
	if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1){
		printf("socket() error\n");
		exit(1);
	}
	bzero(&server,sizeof(server));
	server.sin_family=AF_INET;
	server.sin_port=htons(PORT);
	server.sin_addr=*((struct in_addr *)he->h_addr);
	if(connect(sockfd,(struct sockaddr *)&server,sizeof(server))==-1){
		printf("connect() error\n");
		exit(1);
	}
	process(stdin,sockfd);
	close(sockfd);
}
void process(FILE *fp,int sockfd){
	char sendline[MAXDATASIZE],recvline[MAXDATASIZE];
	int num;
	printf("Connected to server.\n");
	printf("Input client's name:");
	if(fgets(sendline,MAXDATASIZE,fp)==NULL){
		printf("\nExit.\n");
		return;
	}
	send(sockfd,sendline,strlen(sendline),0);
	while(getMessage(sendline,MAXDATASIZE,fp)!=NULL){
		send(sockfd,sendline,strlen(sendline),0);
		if((num=recv(sockfd,recvline,MAXDATASIZE,0))==0){
			printf("Server terminated.\n");
			return;
		}
		recvline[num]='\0';
		printf("Server Message:%s\n",recvline);
	}
	printf("\nExit.\n");
}
char* getMessage(char* sendline,int len,FILE* fp){
	printf("Input string to server:");
	return(fgets(sendline,MAXDATASIZE,fp));
}	

執行示例