2024/4/16 网络编程day4

/*TCP并发服务器端*/
#include <myhead.h>
#define SER_IP "192.168.125.173"
#define SER_PORT 8888
void sighanger(int signum){
	if(signum==SIGCHLD){//子进程终止信号
		while(waitpid(-1,NULL,WNOHANG)>0);//循环回收僵尸进程
	}
}

int main(int argc, const char *argv[])
{
	//函数调用出错返回SIG_ERR

	if(signal(SIGCHLD,sighanger)==SIG_ERR){
		perror("signal error");
		return -1;
	}
	//创建套接字
	int rfd=socket(AF_INET,SOCK_STREAM,0);
	if(rfd==-1){
		perror("socket error");
		return -1;
	}
	printf("socket success\n");

	//为服务器绑定ip地址端口号
	struct sockaddr_in cin;
	cin.sin_family=AF_INET;
	cin.sin_port=htons(SER_PORT);
	cin.sin_addr.s_addr=inet_addr(SER_IP);
	if(bind(rfd,(struct sockaddr*)&cin,sizeof(cin))==-1){
			perror("bind error");
			return -1;
			}
	//设置监听
	if(listen(rfd,128)==-1){
		perror("listen error");
		return -1;
	}
	printf("listen success\n");
	struct sockaddr_in sin;
	socklen_t socklen=sizeof(sin);
	while(1){//循环接收客户端请求
		int newfd=accept(rfd,(struct sockaddr*)&sin,&socklen);
		if(newfd==-1){
			perror("accept error");
			return -1;
		}
		pid_t pid=fork();
		if(pid>0){
			close(newfd);
		}else if(pid==0){//子进程数据通信
			close(rfd);
			char rbuf[128]="";
			while(1){
				bzero(rbuf,sizeof(rbuf));
				int res=read(newfd,rbuf,sizeof(rbuf));
				if(res==0){

					printf("客户端已下线\n");
					break;
				}

				printf("[%s:%d]:%s\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),rbuf);
				//将字符串加777发送回去
				strcat(rbuf,"777");
				write(newfd,rbuf,sizeof(rbuf));
				printf("发送成功\n");

			}
			close(newfd);
			exit(EXIT_SUCCESS);
		}
	}
	close(rfd);
	return 0;
}

//多线程实现TCP并发服务器
#include<myhead.h>
#define SER_IP "192.168.125.117"        //服务器IP地址
#define SER_PORT 8888                   //服务器端口号

//定义用于给线程体传参的结构体类型
struct MsgInfo
{
    int newfd;
    struct sockaddr_in cin;
};

//定义线程体函数
void *deal_cli_msg(void *arg)
{

    //将传递进来的数据解析出来
    int newfd = ((struct MsgInfo*)arg)->newfd;
    struct sockaddr_in cin = ((struct MsgInfo*)arg)->cin;

    //5、数据通信
    char rbuf[128] = "";       //用于接受消息
    while(1)
    {
        bzero(rbuf, sizeof(rbuf));    //清空容器
        //从套接字文件中读取消息
        //int ret = read(newfd, rbuf, sizeof(rbuf));
        int ret = recv(newfd, rbuf, sizeof(rbuf), 0);
        if(ret == 0)
        {
            printf("客户端已下线\n");
            break;
        }
        printf("[%s:%d]: %s\n", \
                inet_ntoa(cin.sin_addr), ntohs(cin.sin_port),rbuf );

        //将字符串加个笑脸回回去
        strcat(rbuf, "*_*");
        //write(newfd, rbuf, strlen(rbuf));
        send(newfd, rbuf, strlen(rbuf), 0);
        printf("发送成功\n");

    }

    //6、关闭套接字
    close(newfd);

    //退出线程
    pthread_exit(NULL);


}



/**主程序**/
int main(int argc, const char *argv[])
{
    //1、创建套节字:用于接收客户端链接请求的
    int sfd = socket(AF_INET, SOCK_STREAM, 0);
    if(sfd == -1)
    {
        perror("socket error");
        return -1;
    }
    printf("socket success sfd = %d\n", sfd);     //3

    //设置端口号快速重用
    int reuse = 1;
    if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse))==-1)
    {
        perror("setsockopt error");
        return -1;
    }
    printf("端口号快速重用成功\n");
    
    //2、绑定IP地址和端口号
    //2.1 填充地址信息结构体
    struct sockaddr_in sin;
    sin.sin_family = AF_INET;       //地址族
    sin.sin_port = htons(SER_PORT);  //端口号
    sin.sin_addr.s_addr = inet_addr(SER_IP);    //IP地址

    //2.2 绑定工作
    if( bind(sfd, (struct sockaddr*)&sin, sizeof(sin)) ==-1)
    {
        perror("bind error");
        return -1;
    }
    printf("bind success\n");


    //3、讲套节字设置成被动监听状态
    if( listen(sfd, 128) == -1)
    {
        perror("listen error");
        return -1;
    }
    printf("listen success\n");

    //4、阻塞等待客户端连接请求
    //定义地址信息结构体变量用于接受客户端的地址信息
    struct sockaddr_in cin;
    socklen_t socklen = sizeof(cin);     //接受地址信息的长度
    
    while(1)
    {
        int newfd = accept(sfd, (struct sockaddr*)&cin, &socklen);
        if(newfd == -1)
        {
            perror("accept error");
            return -1;
        }

        printf("[%s:%d]:已连接, newfd = %d\n",\
                inet_ntoa(cin.sin_addr), ntohs(cin.sin_port) ,newfd);    //4

        //定义用于传参的变量
        struct MsgInfo info = {newfd, cin};
	  //创建分支线程用于通信
        pthread_t tid = -1;
        if(pthread_create(&tid, NULL, deal_cli_msg, &info) != 0)
        {
            printf("线程创建失败\n");
            return -1;
        }
        //回收分支线程的资源
		pthread_detach(tid);

    }

    close(sfd);


    return 0;
}

//流式域套接字服务器端
#include<myhead.h>
int main(int argc, const char *argv[])
{
    //1、创建套节字:用于接收客户端链接请求的
    int sfd = socket(AF_UNIX, SOCK_STREAM, 0);
    if(sfd == -1)
    {
        perror("socket error");
        return -1;
    }
    printf("socket success sfd = %d\n", sfd);     //3

    //判断要绑定的套接字文件是否存在,如果存在,需要将其删除
    if(access("./unix", F_OK) == 0)
    {
        //说明文件存在,需要将其删除
        if(unlink("./unix") != 0)
        {
            perror("unlink error");
            return -1;
        }
    }

    //2、绑定套接字文件
    //2.1 填充地址信息结构体
    struct sockaddr_un sun;
    sun.sun_family = AF_UNIX;    //通信域
    strcpy(sun.sun_path , "./unix");    //套接字文件


    //2.2 绑定工作
    if( bind(sfd, (struct sockaddr*)&sun, sizeof(sun)) ==-1)
    {
        perror("bind error");
        return -1;
    }
    printf("bind success\n");


    //3、讲套节字设置成被动监听状态
    if( listen(sfd, 128) == -1)
    {
        perror("listen error");
        return -1;
    }
    printf("listen success\n");

    //4、阻塞等待客户端连接请求
    //定义地址信息结构体变量用于接受客户端的地址信息
    struct sockaddr_un cun;
    socklen_t socklen = sizeof(cun);     //接受地址信息的长度
    
    int newfd = accept(sfd, (struct sockaddr*)&cun, &socklen);
    if(newfd == -1)
    {
        perror("accept error");
        return -1;
    }

    printf("[%s]:已连接, newfd = %d\n", cun.sun_path,newfd);    //4

    //5、数据通信
    char rbuf[128] = "";       //用于接受消息
    while(1)
    {
        bzero(rbuf, sizeof(rbuf));    //清空容器
        //从套接字文件中读取消息
        //int ret = read(newfd, rbuf, sizeof(rbuf));
        int ret = recv(newfd, rbuf, sizeof(rbuf), 0);
        if(ret == 0)
        {
            printf("客户端已下线\n");
            break;
        }
        printf("[%s]: %s\n", cun.sun_path ,rbuf );

        //将字符串加个笑脸回回去
        strcat(rbuf, "*_*");
        //write(newfd, rbuf, strlen(rbuf));
        send(newfd, rbuf, strlen(rbuf), 0);
        printf("发送成功\n");

    }
    //6、关闭套接字
    close(newfd);
    close(sfd);

    return 0;
}

//报式域套接字服务器端
#include<myhead.h>
int main(int argc, const char *argv[])
{
    //1、创建用于通信的套接字文件描述符
    int sfd = socket(AF_UNIX, SOCK_DGRAM, 0);
    if(sfd == -1)
    {
        perror("socket error");
        return -1;
    }
    printf("socket success sfd = %d\n", sfd);         //3

    //判断要绑定的套接字文件是否存在,如果存在,需要将其删除
    if(access("./unix", F_OK) == 0)
    {
        //说明文件存在,需要将其删除
        if(unlink("./unix") != 0)
        {
            perror("unlink error");
            return -1;
        }
    }
    //2、绑定IP地址和端口号
    //2.1 填充地址信息结构体
    struct sockaddr_un sun;
    sun.sun_family = AF_UNIX;       //协议族
    strcpy(sun.sun_path, "./unix");   //服务器的套接字文件

    //2.2 绑定工作
    if(bind(sfd, (struct sockaddr*)&sun, sizeof(sun)) == -1)
    {
        perror("bind error");
        return -1;
    }
    printf("bind success\n");

    //3、数据的收发
    //定义变量接收客户端地址信息结构体
    struct sockaddr_un cun;
    socklen_t socklen = sizeof(cun);

    char rbuf[128] = "";
    while(1)
    {
        bzero(rbuf, sizeof(rbuf));

        //读取套接字中的数据
        recvfrom(sfd, rbuf, sizeof(rbuf), 0, (struct sockaddr*)&cun, &socklen);
        printf("[%s]:%s\n",cun.sun_path, rbuf);

        //加个笑脸将消息回回去
        strcat(rbuf, "*_*");
        if(sendto(sfd, rbuf, strlen(rbuf), 0, (struct sockaddr*)&cun, sizeof(cun)) ==-1)
        {
            perror("write error");
            return -1;
        }
        printf("发送成功\n");

    }

    //4、关闭套接字
    close(sfd);

    return 0;
}

通过TFTP用UDP实现上传和下载文件

#include <myhead.h>
#define SER_IP "192.168.125.99"
#define SER_PORT 69
#define IP "192.168.125.173"
#define PORT 8888
void download(char data[],short* p1,char* p2){
		char filename[128]="";
		printf("请输入要下载的文件名:");
		fgets(filename,sizeof(filename),stdin);
		filename[strlen(filename)-1]=0;
		int fp=open(filename,O_WRONLY | O_CREAT|O_TRUNC, 0664);//创建文件
		if(fp==-1){
			perror("open error");
			return ;
		}
		*p1=htons(1);//下载
		strcpy(p2,filename);
		char* p4=p2+strlen(filename)+1;
		strcpy(p4,"octet");
		int len=4+strlen(filename)+strlen("octet");
		printf("%s\n",p2);
		int sfd=socket(AF_INET,SOCK_DGRAM,0);
		if(sfd==-1){
			perror("socket error");
			return ;
		}
		struct sockaddr_in rin;
    	rin.sin_family=AF_INET;
		rin.sin_port=htons(PORT);
		rin.sin_addr.s_addr=inet_addr(IP);
		if(bind(sfd,(struct sockaddr*)&rin,sizeof(rin))==-1){
			perror("bind error");
			return ;
		}
		printf("bind success\n");
		struct sockaddr_in sin;
    	sin.sin_family=AF_INET;
		sin.sin_port=htons(SER_PORT);
		sin.sin_addr.s_addr=inet_addr(SER_IP);	
		socklen_t sin_size = sizeof(sin);  
		//发送下载请求
		sendto(sfd,data,len,0,(struct sockaddr*)&sin,sizeof(sin));
		char buf[516];
		short ack[2];
		ack[0]=htons(4);
		int res;
		while(1){
			bzero(buf,sizeof(buf));
			//接收数据到buf
			res=recvfrom(sfd, buf, sizeof(buf), 0, (struct sockaddr*)&sin, &sin_size);
			//返回接收数据字节数
			//从返回数据包中取出块编号,放到ack中去
			ack[1]=*(short*)(buf+2);
			
			//返回ACK确认
			
			sendto(sfd, ack, sizeof(ack), 0, (struct sockaddr*)&sin, sin_size);
			//将buf中的数据写到文件
			write(fp,buf+4,res-4);//写res-4个数据从buf+4位置到文件
			if(res!=516){
				break;
			}
		}
		close(fp);
}
void transmit(char data[],short* p1,char* p2){
	char filename[128]="";
	printf("请输入要上传的文件名:");
	fgets(filename,sizeof(filename),stdin);
	filename[strlen(filename)-1]=0;
	*p1=htons(2);//写,上传请求
	int fp=open(filename,O_RDONLY, 0664);//打开文件
	strcpy(p2,filename);
	char* p4=p2+strlen(filename)+1;
	strcpy(p4,"octet");
	int len=4+strlen(filename)+strlen("octet");
	int sfd=socket(AF_INET,SOCK_DGRAM,0);
		if(sfd==-1){
			perror("socket error");
			return ;
		}
		struct sockaddr_in rin;
    	rin.sin_family=AF_INET;
		rin.sin_port=htons(PORT);
		rin.sin_addr.s_addr=inet_addr(IP);
		if(bind(sfd,(struct sockaddr*)&rin,sizeof(rin))==-1){
			perror("bind error");
			return ;
		}
		printf("bind success\n");
		struct sockaddr_in sin;
    	sin.sin_family=AF_INET;
		sin.sin_port=htons(SER_PORT);
		sin.sin_addr.s_addr=inet_addr(SER_IP);	
		socklen_t sin_size = sizeof(sin);  
		//发送下载请求
		sendto(sfd,data,len,0,(struct sockaddr*)&sin,sizeof(sin));
		int count=1;
		*p1=htons(3);
		short* p10=data+2;
		while(1){
			*p10=htons(count);
			int ress=read(fp,data+4,512);
			if(ress==0){break;}
			sendto(sfd, data, sizeof(data), 0, (struct sockaddr*)&sin, sin_size);
			count++;


		}

	close(fp);
}
int main(int argc, const char *argv[])
{

	printf("1.下载2.上传");
	printf("请输入>>>");
	int flag=0;
	scanf("%d",&flag);
	while(getchar()!=10);
	char data[516]="";
	short* p1=data;
	char* p2=data+2;
	if(flag==1){
		download(data,p1,p2);
	}else if(flag==2){
		transmit(data,p1,p2);
	}
	
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值