TCP并发服务器的简易程序

5 篇文章 0 订阅
4 篇文章 0 订阅

1.服务器采用简易线程开启,将传送过来的字母转换为大写再发送过去,如果传送过来的第一个字符为@则退出

2.客户端循环读入,如果输入@则退出当前socket

 服务器程序:server_thread.c

#include<stdlib.h>
#include<stdio.h>
#include<errno.h>
#include<string.h>
#include<netdb.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<unistd.h>
#include<sys/un.h>
#include<sys/wait.h>
#include<signal.h>
#include<pthread.h>


void* thr_fn(void* arg)
{
	int n_read;
	char sz_buff[1024];
	int n_newfd = *((int*)arg);
	int j;
	printf("new socket: %d\n",n_newfd);
	
	//从客户端读取数据
	while( ( n_read=read(n_newfd,sz_buff,1024) ) > 0 )
	{
		if(sz_buff[0]=='@')
		{
			printf("socket(%d) out ...\n", n_newfd);
			close(n_newfd);
			break;
		}
		printf("read %d byte data from client:%s",n_read,sz_buff);
		
		//将读取的数据全部转换为大写
		for(j=0; j<n_read; j++)
		{
			sz_buff[j]=toupper(sz_buff[j]);
		}	
		//将转换后的字符串再发送出去
		if(write(n_newfd,sz_buff,n_read)==-1)
		{
			fprintf(stderr,"write data  error: %s\n", strerror(errno));
			exit(1);
		}
		memset(sz_buff,0,1024);
	}
	close(n_newfd);
	
	return 0;
}
	
		

int main(int argc,char* argv[])
{
	
	int n_sockfd, n_newfd;
	struct sockaddr_in st_server;
	struct sockaddr_in st_client;
	
	int n_client_size,n_read_size;
	socklen_t n_addr_len;	
	
	int n_port;
	char sz_buff[1024];
	pthread_t pid;
	
	if(argc != 2)
	{
		printf("please input argument\n");
		exit(1);
	}
	
	if( (n_sockfd=socket(PF_INET,SOCK_STREAM,0))==-1)
	{
		fprintf(stderr,"scoket error:%s\n",strerror(errno));
		exit(1);
	}
	
	//bzero(&st_server,sizeof(st_server));
	memset(&st_server,0,sizeof(st_server));
	st_server.sin_family=AF_INET;
	st_server.sin_addr.s_addr=htonl(INADDR_ANY);
	st_server.sin_port=htons( atoi(argv[1]) );
	
	if(bind(n_sockfd,(struct sockaddr*)&st_server,sizeof(st_server))==-1)
	{
		fprintf(stderr,"bind server error:%s\n\a",strerror(errno));
		close(n_sockfd);
		exit(1);
	}
	
	if(listen(n_sockfd,2)==-1)
	{
		fprintf(stderr,"listen error:%s\n\a",strerror(errno));
		close(n_sockfd);
		exit(1);
	}
	
	while(1)
	{
		n_client_size=sizeof(st_client);
		if( (n_newfd=accept(n_sockfd,(struct sockaddr*)&st_client,&n_client_size))==-1)
		{
			if(errno==EINTR)
			{
				continue;
			}
			fprintf(stderr,"accept error:%s\n\a",strerror(errno));
			close(n_sockfd);
			exit(1);
		}
		fprintf(stderr,"server get connet from:%s\n",inet_ntoa(st_client.sin_addr));
		printf("new socket: %d\n",n_newfd);
		
		//创建线程
		if( (pthread_create(&pid,NULL,thr_fn,&n_newfd))==-1)
		{
			fprintf(stderr,"create thread error:%s\n",strerror(errno));			
			close(n_newfd);
			close(n_sockfd);
			exit(1);
		}
	}
	//close(n_sockfd);
	exit(0);	
}
	


 
客户端程序:client_thread.c

#include<stdlib.h>
#include<stdio.h>
#include<errno.h>
#include<string.h>
#include<netdb.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<sys/un.h>
#include<unistd.h>

#define PORT_NUM 3333

int main(int argc,char*argv[])
{
	int n_sockfd;
	struct sockaddr_in st_server;
	char sz_buff[1024];
	struct hostent* pst_host;
	int n_port;
	int n_read;
	
	if(argc != 3)
	{
		fprintf(stderr,"please input argument\n");
		exit(1);
	}
	
	/*
	if( (pst_host=gethostbyname(argv[1]))==NULL)
	{
		fprintf(stderr,"gethostname error:%s\n",strerror(errno));
		exit(1); 
	}
	*/
	
	
	if( (n_sockfd=socket(PF_INET,SOCK_STREAM,0))==-1)
	{
		fprintf(stderr,"scoket error:%s\n",strerror(errno));
		exit(1);
	}
	
	//bzero(&st_server,sizeof(st_server));
	memset(&st_server,0,sizeof(st_server));
	st_server.sin_family=AF_INET;
	//st_server.sin_addr=*((struct in_addr*)pst_host->h_addr);
	//pst_host 是一个指针指向in_addr*类型的数组
	st_server.sin_addr.s_addr=inet_addr(argv[1]);
	st_server.sin_port=htons(atoi(argv[2]));
	
	if(connect(n_sockfd,(struct sockaddr*)&st_server,sizeof(st_server))==-1)
	{
		fprintf(stderr,"connect server error:%s\n\a",strerror(errno));
		close(n_sockfd);
		exit(1);
	}
	
	while(1)
	{	
		  //输入数据提示
			if( write(STDOUT_FILENO,"\nplease input data:",20)==-1)
			{
				fprintf(stderr,"write error:%s\n",strerror(errno));
				exit(1);
			}
			
			//读取输入的数据,并发送给服务器
			memset(sz_buff,0,1024);
			n_read=read(STDIN_FILENO,sz_buff,1024);			
			printf("n_read = %d,send message: %s",n_read,sz_buff);
			
			if(n_read>0)
			{			
				if( write(n_sockfd,sz_buff,n_read)==-1)
				{
					fprintf(stderr,"write error:%s\n",strerror(errno));
					exit(1);
				}
			}
			
			//如果读取的第一个数据位@则推出循环
			if( sz_buff[0]=='@' )
			{
				break;
			}
			
			//从服务器读取数据
			memset(sz_buff,0,1024);
			printf("n_sockfd = %d\n",n_sockfd);
			n_read=read(n_sockfd,sz_buff,n_read);
			printf("read message: %s",sz_buff);
			if(n_read>0)
			{
				printf("get message from server: %s",sz_buff);
			}
	}
	close(n_sockfd);
	
	exit(0);	
}
	

调式结果:


注:切记不要在服务器段提前关闭socket,服务器监听套接字不能关闭,一直处于循环等待中

       一旦客户端关闭socket,就不能再发送数据了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值