嵌入式学习-网络编程-Day3

发布时间:2024年01月17日

思维导图

Day3.png

多进程并发服务器通信模型如下

void handler(int signo)
{
    while(waitpid()>0);      //以非阻塞配合信号完成僵尸进程的回收
}
int  main()
{
    //将信号与信号处理函数绑定
    signal(SIGCHLD, handler);
 
    socket();    //创建用于连接的套接字
    bind();           //绑定IP地址和端口号
    listen();           //将套接字设置成被动监听状态
     while(1)
     {
         newfd = accept();           //接收客户端连接请求
         fd = fork();           //创建子进程用于通信
         if(pid > 0)
         {
             //父进程中关闭newfd
             close(newfd);         
         } else if(pid == 0)
         {
             close(sfd);          //关闭sfd
             //子进程用于通信
             recv();
             send();
             close(newfd);       
             exit(EXIT_SUCCESS);     //退出子进程  
         }             
     }    
      close(sfd);   关闭监听 
}

多线程实现TCP并发服务器的通信模型如下

socket();         //创建套接字
bind();             //必须绑定
listen();            //设置被动监听
while(1)
{
    newfd = accept();            //接收客户端连接请求
    //创建分支线程,用于跟客户端进行交互
    pthread_create(&tid, NULL, deal_cli_msg, &info);
    
    //线程分离
    pthread_detach(tid);
}
//线程处理函数的定义
void *deal_cli_msg(void *arg)
{
    recv();
    send();
    close();
    pthread_exit();
}

作业:编写一个客户端,通过TFTP服务器实现文件的上传和下载

部分代码如下

#include<myhead.h>
#define SER_PORT 69
#define SER_IP "192.168.122.71"

int do_download(int cfd,struct sockaddr_in sin)
{
    //向服务器发送下载请求
    char buf[516] = "";
	 //组装请求数据
    short *p1 = (short *)buf;
    *p1 = htons(1);
    
    char *p2 = buf+2;
    char filename[24]="";
    printf("请输入要下载的文件名>>>");
    scanf("%s",filename);
    getchar();
    strcpy(p2, filename);

    char *p3 = p2+strlen(p2)+1;
    strcpy(p3, "octet");

    int len = 4+strlen(p2) + strlen(p3);   //要发送的长度

    //向服务器发送请求
    sendto(cfd, buf, len, 0, (struct sockaddr*)&sin, sizeof(sin));
    printf("下载请求已发送\n");
    
    int fd = -1;
    int res=0;
    //循环收发 
    while(1)
    {
        //客户端收取数据包
        bzero(buf,sizeof(buf));
        if(res=recvfrom(cfd,buf,sizeof(buf),0,NULL,NULL)==-1)
        {
            perror("recv error");
            break;
        }
        
        short *opera_id=(short *)buf; //操作码
        short bid;  //块编号
        if(*opera_id==3)
        {
            *opera_id=4;
            //块编号
            short *pbid=(short*)buf+2;
            bid=(short)(*pbid);

            //数据
            char *pdata=(char*)pbid+2;
            int datalen = strlen(pdata);
            if((*pbid)==1)
            {
                if(fd=open(filename,O_WRONLY|O_CREAT|O_APPEND,0664)==-1)
                {
                    perror("open error");
                    return -1;
                }
            }

            if(write(fd,pdata,res-4)==-1)
            {
                perror("write all");
                break;
            }

            //ACK
            //发送ACK包
            sendto(cfd,buf,4,0,(struct sockaddr*)&sin,sizeof(sin));
            if(res <516 )
            {
                puts("下载完成");
                break;
            }
        }
    }
    puts("下载完成");
    close(fd);
    return 0;
}

int do_upload(int cfd,struct sockaddr_in sin)
{


}

int main(int argc, const char *argv[])
{
    //1、创建用于通信的套接字文件描述符
    int cfd = socket(AF_INET, SOCK_DGRAM, 0);
    if(cfd == -1)
    {
        perror("socket error");
        return -1;
    }

    //2、绑定(可选)
    
    //3、填充服务器的地址信息结构体
    struct sockaddr_in sin;
    sin.sin_family = AF_INET;
    sin.sin_port = htons(SER_PORT);
    sin.sin_addr.s_addr = inet_addr(SER_IP);

    char menu;

	//制作菜单框架
	while(1)
	{
		printf("\t\t====1.download====\n");
		printf("\t\t====2.upload====\n");
		printf("\t\t====0.exit====\n");
		
		printf("Please enter function options:");
		scanf("%c",&menu);
		while(getchar() != '\n');

		//对菜单选项多分支选择
		switch(menu)
		{
			case '1':    
				{
					do_download(cfd,sin);  //下载
				}
				break;
			case '2':
				{
					do_upload(cfd,sin);     //上传
				}
				break;
			case '0':
					exit(1);
			default:
				{
					printf("enter error!!!");
				}
		}
		printf("Enter any key to clear the screen:");
		while(getchar() != '\n');
		system("clear");
	}
    //5、关闭套接字
    close(cfd);


    return 0;
}

文章来源:https://blog.csdn.net/m0_56018621/article/details/135640246
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。