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实现上传和下载文件

cs 复制代码
#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;
}
相关推荐
小堃学编程3 小时前
计算机网络(十) —— IP协议详解,理解运营商和全球网络
网络·tcp/ip·计算机网络
IPFoxy6666 小时前
探索路由器静态IP的获取方式
网络·智能路由器
menge23336 小时前
VLAN:虚拟局域网
网络·智能路由器
ZachOn1y6 小时前
计算机网络:计算机网络概述 —— 初识计算机网络
网络·计算机网络·知识点汇总·考研必备
三金121387 小时前
SpringIoC容器的初识
网络·网络协议·rpc
狼头长啸李树身8 小时前
眼儿媚·秋雨绵绵窗暗暗
大数据·网络·服务发现·媒体
SizeTheMoment9 小时前
初识HTTP协议
网络·网络协议·http
哲伦贼稳妥9 小时前
一天认识一个硬件之机房地板
运维·网络·经验分享·其他
hgdlip11 小时前
如何快速切换电脑的ip地址
网络·tcp/ip·电脑
程序员-珍12 小时前
虚拟机ip突然看不了了
linux·网络·网络协议·tcp/ip·centos