网络编程 TCP多并发服务器 tftp上传下载

TCP多并发服务器

多线程

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



void* test_send(void* arg){
	char buf[20]="";
	int accfd=*(int *)arg;
	while(1){
		bzero(buf,sizeof(buf));
		//sleep(1);
		printf("请输入:\n");
		scanf("%s",buf);
		int sndres=send(accfd,(void*)buf,sizeof(buf),0);  //发送信息给客户端
		if(sndres>0){
			printf("已发送%d个字节\n",sndres);
		}else if(sndres<0){
			perror("send");
		}
	}
	close(accfd);
	pthread_exit(NULL);
}

void* test_recv(void* arg){
	char buf[20];
	int accfd=*(int *)arg;
	while(1){
		bzero(buf,sizeof(buf));
		int recres=recv(accfd,(void*)buf,sizeof(buf),0);   //接收客户端信息
		if(recres>0){
			printf("已接受%d个字节\n",recres);
			printf("res=%s\n",buf);
		}else if(recres==0){
			printf("客户端已关闭\n");
			break;
		}else{
			perror("recv");
			return NULL;
		}
	}
	close(accfd);
	pthread_exit(NULL);
}




void main_serv(){
	struct sockaddr_in addr;
	addr.sin_family=AF_INET;
	addr.sin_port=htons(8888);   //端口号   本机字节序--->网络字节序
	addr.sin_addr.s_addr=inet_addr("192.168.8.207"); //ip 本机字节序--->网络字节序


	int sockfd=socket(AF_INET,SOCK_STREAM,0);
	if(sockfd<0){
		perror("socket");
		return;
	}

	//端口号快速重用
	int reuse=1;
	if(setsockopt(sockfd,SOL_SOCKET, SO_REUSEADDR, &reuse ,sizeof(reuse))<0){
		perror("setsockopt");
		return;
	}

	if(bind(sockfd,(struct sockaddr*)&addr,sizeof(addr))<0){
		perror("bind");
		return;
	}
	
	if(listen(sockfd,32)!=0){
		perror("listen");
		return;
	}

	struct sockaddr_in raddr;
	int len=sizeof(raddr);
	pthread_t tid_s;
	pthread_t  tid_r;
	int accfd;
	while(1){
	accfd=accept(sockfd,(struct sockaddr*)&raddr,&len);
	if(accfd<0){
		perror("accept");
		return;
	}
	
//	char* ip=inet_ntoa(raddr.sin_addr);
//	printf("ip:%s\n",ip);
	
	
	/*
	char w_buf[20]="rogar";
		char r_buf[20]="";
	while(1){	
		int recres=recv(accfd,r_buf,sizeof(r_buf),0);   //接收客户端信息
		if(recres>0){
			printf("已接受%d个字节\n",recres);
			printf("%s\n",r_buf);
		}else if(recres==0){
			printf("客户端已关闭\n");
			break;
		}else{
			perror("recv");
			return ;
		}


		int sndres=send(accfd,w_buf,sizeof(w_buf),0);  //发送信息给客户端
		if(sndres>0){
			printf("已发送%d个字节\n",sndres);
		}else if(sndres<0){
			perror("send");
		}
		





		}

	*/
	
//	pthread_t tid_s;
//	pthread_t  tid_r;
	pthread_create(&tid_s,NULL,test_send,(void*)&accfd);
	pthread_create(&tid_r,NULL,test_recv,(void*)&accfd);
	pthread_detach(tid_s);
	pthread_detach(tid_r);
	}


	//close(accfd);
	close(sockfd);


}



int main(){
	main_serv();
}

多进程

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

/*
void* test_send(void* arg){
	char buf[20]="";
	int accfd=*(int *)arg;
	while(1){
		bzero(buf,sizeof(buf));
		//sleep(1);
		printf("请输入:\n");
		scanf("%s",buf);
		int sndres=send(accfd,(void*)buf,sizeof(buf),0);  //发送信息给客户端
		if(sndres>0){
			printf("已发送%d个字节\n",sndres);
		}else if(sndres<0){
			perror("send");
		}
	}
}

void* test_recv(void* arg){
	char buf[20];
	int accfd=*(int *)arg;
	while(1){
		bzero(buf,sizeof(buf));
		int recres=recv(accfd,(void*)buf,sizeof(buf),0);   //接收客户端信息
		if(recres>0){
			printf("已接受%d个字节\n",recres);
			printf("res=%s\n",buf);
		}else if(recres==0){
			printf("客户端已关闭\n");
			break;
		}else{
			perror("recv");
			return NULL;
		}
	}
}

*/

void handler(int sig){
	while(waitpid(-1,NULL,WNOHANG)>0);
}


void main_serv(){
	signal(SIGCHLD,handler);

	struct sockaddr_in addr;
	addr.sin_family=AF_INET;
	addr.sin_port=htons(8888);   //端口号   本机字节序--->网络字节序
	addr.sin_addr.s_addr=inet_addr("192.168.8.207"); //ip 本机字节序--->网络字节序


	int sockfd=socket(AF_INET,SOCK_STREAM,0);
	if(sockfd<0){
		perror("socket");
		return;
	}

	//端口号快速重用
	int reuse=1;
	if(setsockopt(sockfd,SOL_SOCKET, SO_REUSEADDR, &reuse ,sizeof(reuse))<0){
		perror("setsockopt");
		return;
	}

	if(bind(sockfd,(struct sockaddr*)&addr,sizeof(addr))<0){
		perror("bind");
		return;
	}
	
	if(listen(sockfd,32)!=0){
		perror("listen");
		return;
	}

	struct sockaddr_in raddr;
	int len=sizeof(raddr);
	while(1){
	int accfd=accept(sockfd,(struct sockaddr*)&raddr,&len);
	if(accfd<0){
		perror("accept");
		return;
	}
	pid_t pid=fork();
	if(pid>0){
		//父进程负责监听
		close(accfd); 
	}else if(pid==0){
		//子进程负责接收发送
		close(sockfd);
		char r_buf[20]="";
	while(1){	
		int recres=recv(accfd,r_buf,sizeof(r_buf),0);   //接收客户端信息
		if(recres>0){
			printf("已接受%d个字节\n",recres);
			printf("%s\n",r_buf);
		}else if(recres==0){
			printf("客户端已关闭\n");
			break;
		}else{
			perror("recv");
			return ;
		}

		char w_buf[10]="okok";
		int sndres=send(accfd,w_buf,sizeof(w_buf),0);  //发送信息给客户端
		if(sndres>0){
			printf("已发送%d个字节\n",sndres);
		}else if(sndres<0){
			perror("send");
		}
		

		}
		exit(0);

	}else{
		perror("fork");
		return;

	}
}
	
	
	/*
	char w_buf[20]="rogar";
		char r_buf[20]="";
	while(1){	
		int recres=recv(accfd,r_buf,sizeof(r_buf),0);   //接收客户端信息
		if(recres>0){
			printf("已接受%d个字节\n",recres);
			printf("%s\n",r_buf);
		}else if(recres==0){
			printf("客户端已关闭\n");
			break;
		}else{
			perror("recv");
			return ;
		}


		int sndres=send(accfd,w_buf,sizeof(w_buf),0);  //发送信息给客户端
		if(sndres>0){
			printf("已发送%d个字节\n",sndres);
		}else if(sndres<0){
			perror("send");
		}
		

		}

	*/
	/*
	pthread_t tid_s;
	pthread_t  tid_r;


	pthread_create(&tid_s,NULL,test_send,(void*)&accfd);
	pthread_create(&tid_r,NULL,test_recv,(void*)&accfd);

	pthread_join(tid_r,NULL);
	pthread_join(tid_s,NULL);
*/

	//close(accfd);
	close(sockfd);




	

}



int main(){
	main_serv();
}

tftp 下载上传

#include <stdio.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h> 
#include <errno.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
/*
typedef struct {
	int sockfd;
	struct sockaddr_in dest;

}node;
*/



void download(int sockfd,struct sockaddr_in addr){
	char filename[20]="";
	char buf[516];
	bzero(filename,sizeof(filename));
	printf("输入文件名:\n");
	//scanf("%s",filename);
	//while(getchar()!='\n'){}
	fgets(filename,sizeof(filename),stdin);
	filename[strlen(filename)-1]=0;
	//读写请求拼接
//	struct sockaddr_in dest_server=n->dest;
	//操作码   1--下载  2--上传
	short* p_code=(short*)buf;
	*p_code=htons(1);
	
	//文件名
	char* p_filename=(char *)buf+2;
	strcpy(p_filename,filename);
	
	//标识1
	char *p_flag1=(char *)buf+2+strlen(filename);
	*p_flag1=0;

	//模式
	char *p_mode=(char *)buf+2+strlen(filename)+1;
	strcpy(p_mode,"octet");
	// 标识2
	char *p_flag2=(char *)buf+2+strlen(filename)+1+5;
	*p_flag2=0;

	int size=1+2+1+5+strlen(filename);
	//发送读写请求
	
	if(sendto(sockfd,buf,size,0,(struct sockaddr*)&addr,sizeof(addr))<0){
		perror("48---sendto");
		return ;
	}

	//接收数据
	char buf_recv[600];   				//接收数据的数组
	char* get_bid=buf_recv+2;          //数据包块编号
	char* get_data=buf_recv+4;        //数据包数据

	char ack[4];                      //ACK包
	short* ack_code=(short*)ack;                 //ACK操作码
	short* ack_bid=(short*)ack+1;                //ACK编号
	
	int res;
	int fd=-1;
	int flag=0;
	struct sockaddr_in rec;
	int len=sizeof(rec);
	while(1){
		
		if((res=recvfrom(sockfd,buf_recv,sizeof(buf_recv),0,(struct sockaddr*)&rec,&len))<516){
			if(buf_recv[1]==5){
				fprintf(stderr, "错误码:%d 错误信息:%s\n", ntohs(*(unsigned short*)(buf_recv+2)), buf_recv+4);
				break;
			}	
			printf("接收完毕\n");
			break;
		}
		if(res<0){
			return;
		}
		if(buf_recv[1]==3){
			if(flag==0){
		int fd=open(filename,O_RDWR|O_CREAT,0777);
			if(fd<0){
				perror("open");
				return ;
			}
			flag=1;
		}
		write(fd,get_data,res-4);
		//组ACK
		*ack_code=htons(4);
		*ack_bid=*(short*)get_bid;
		
		//发送ACK
		sendto(sockfd,ack,4,0,(struct sockaddr*)&rec,sizeof(rec));
		}else if(buf_recv[1]==5){
			fprintf(stderr, "错误码:%d 错误信息:%s\n", ntohs(*(unsigned short*)(buf_recv+2)), buf_recv+4);
			break;
		}
		
	}

	//组ACK
	*ack_code=htons(4);
	*ack_bid=*(short*)get_bid;
	//发送ACK
	sendto(sockfd,ack,4,0,(struct sockaddr*)&rec,sizeof(rec));
	write(fd,get_data,res-4);
	close(fd);
}



void upload(int sockfd,struct sockaddr_in addr){
	char filename[20]="";
	bzero(filename,sizeof(filename));
	printf("输入文件名:\n");
	fgets(filename,sizeof(filename),stdin);
	filename[strlen(filename)-1]=0;
	//读写请求拼接
	char buf[128];
//	struct sockaddr_in dest_server=np->dest;
	//操作码   1--下载  2--上传
	short* p_code=(short*)buf;
	*p_code=htons(2);
	
	//文件名
	char* p_filename=(char *)buf+2;
	strcpy(p_filename,filename);
	
	//标识1
	char *p_flag1=(char *)buf+2+strlen(filename);
	*p_flag1=0;

	//模式
	char *p_mode=(char *)buf+2+strlen(filename)+1;
	strcpy(p_mode,"octet");
	// 标识2
	char *p_flag2=(char *)buf+2+strlen(filename)+1+5;
	*p_flag2=0;

	int size=1+2+1+5+strlen(filename);
	//发送读写请求
	if(sendto(sockfd,buf,size,0,(struct sockaddr*)&addr,sizeof(addr))<0){
		perror("sendto");
		return ;
	}
	

	//打开文件
	int fd=open(filename,O_RDWR);
	if(fd<0){
		perror("open");
		return;
	}
	
	char str[600];  //数据包
	char buf_r[512];  //文件读取存储数组
	char temp[4];    //ACK存储数组
	short* data_code=(short*)str;
	short* data_id=(short*)str+1;
	char* data=str+4;
	short* ack_code=(short*)temp;
	short* ack_bid=(short*)temp+1;

	int res;
	short num=1; //块编号
	struct sockaddr_in ack;
	int len=sizeof(ack);

	recvfrom(sockfd,temp,4,0,(struct sockaddr*)&ack,&len);//接收服务器ack

	while(1){
		
		//组数据包
		*data_code=htons(3);  //数据包操作码
		*data_id=htons(num);   //数据包编号
		num++;
		if((res=read(fd,buf_r,sizeof(buf_r)))<512){
			break;
		}
		strcpy(data,buf_r);
		sendto(sockfd,str,res+4,0,(struct sockaddr*)&ack,sizeof(ack));
		recvfrom(sockfd,temp,4,0,(struct sockaddr*)&ack,&len);//接收服务器ack
		
		
	}
	strcpy(data,buf_r);	
	sendto(sockfd,str,res+4,0,(struct sockaddr*)&ack,sizeof(ack));
	printf("上传完成\n");
		close(fd);
}



/*
node* client_tftp(){
	
	int sockfd=socket(AF_INET,SOCK_DGRAM,0);
	if(sockfd<0){
		perror("sockfd");
		return NULL;
	}
	
	struct sockaddr_in addr;
	addr.sin_family=AF_INET;
	addr.sin_port=htons(69);
	addr.sin_addr.s_addr=inet_addr("192.168.8.226");
	bind(sockfd,(struct sockaddr*)&addr,sizeof(addr));

	node n;
	node *p=&n;
	p->sockfd=sockfd;
	p->dest=addr;

	return p;
}
*/




int main(int argc ,char *argv[]){

	int sockfd=socket(AF_INET,SOCK_DGRAM,0);
	if(sockfd<0){
		perror("sockfd");
		return 0;
	}
	
	struct sockaddr_in addr;
	addr.sin_family=AF_INET;
	addr.sin_port=htons(69);
	addr.sin_addr.s_addr=inet_addr("192.168.8.226");
	bind(sockfd,(struct sockaddr*)&addr,sizeof(addr));




	char c;
	while(1){
		system("clear");
	printf("=======================\n");
	printf("=======1.下载==========\n");
	printf("=======2.上传==========\n");
	printf("=======3.退出==========\n");
	printf("=======================\n");
	printf("请输入选项:");
	c=getchar();
	while(getchar()!=10);
	switch(c){
		case '1':
			download(sockfd,addr);
			break;
		
		case '2':
			upload(sockfd,addr);
			break;

		case '3':
			printf("已退出");
			exit(0);
			break;
		default:
			printf("输入不正确\n");
	}
	printf("输入回车继续");
	while(getchar()!=10){}
	}
	close(sockfd);
	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值