20240818作业

#include<head.h>

#define SER_PORT 69
#define SER_IP "192.168.106.1"
#define CIL_PORT 5555
#define CIL_IP "192.168.106.128"
int main(int argc, char const *argv[])
{
    int cfd=socket(AF_INET,SOCK_DGRAM,0);
    if(cfd==-1)
    {
        perror("socket error");
        return -1;
    }
    printf("cfd=%d\n",cfd);
    //2.向服务器发送下载请求
    char buf[516]="";
    char arr[10]="";
    int a;
    while(1)
    {
        printf("<<<1.下载>>>\n");
        printf("<<<2.上传>>>\n");
        printf("<<<3.退出>>>\n");
        printf("请输入要执行的操作:");
        scanf("%d",&a);
        switch(a)
        {
            case 1://下载
            {
                bzero(buf,sizeof(buf));
                short *p1=buf; //操作码
                *p1=htons(1);
                printf("请输入要下载的文件名:");
                getchar();
                fgets(arr,sizeof(arr),stdin);
                arr[strlen(arr)-1]=0;
                char *p2=buf+2;  //文件名
                strcpy(p2,arr);

                char *p4=p2+strlen(p2)+1;  //模式位
                strcpy(p4,"octet");
                int size=2+strlen(p2)+strlen(p4)+2; //请求包总长度
                //将请求包发送给服务器
                struct sockaddr_in sin;
                sin.sin_family=AF_INET;
                sin.sin_port=htons(SER_PORT);
                sin.sin_addr.s_addr=inet_addr(SER_IP);

                sendto(cfd,buf,size,0,(struct sockaddr*)&sin,sizeof(sin));
                printf("发送请求成功\n");
                int fd=-1;//创建一个无效文件描述符  
                unsigned short num=1;
                ssize_t res=0;
                socklen_t addrlen = sizeof(sin);   //接受地址长度
                while(1)
                {
                    bzero(buf,sizeof(buf));
                    res=recvfrom(cfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,&addrlen);
                    if(buf[1]==3)
                    {
                        if(*(unsigned short*)(buf+2)==htons(num))
                        {
                            num++;
                            if(fd==-1)
                            {
                                fd=open(arr,O_CREAT|O_TRUNC|O_WRONLY,0664);
                                if(fd<0)
                                {
                                    perror("open error");
                                    return -1;
                                }
                            }
                                write(fd,buf+4,res-4);
                                buf[1]=4;
                                sendto(cfd,buf,4,0,(struct sockaddr*)&sin,sizeof(sin));
                                if(res<516)
                                {
                                    printf("文件下载完毕\n");
                                    break;
                                }
                            }
                        }
                    }
                    close(fd);
            }break;
            case 2://上传
            {
                bzero(buf,sizeof(buf));
                short *p1=buf; //操作码
                *p1=htons(2);
                printf("请输入要上传的文件名:");
                getchar();
                fgets(arr,sizeof(arr),stdin);
                arr[strlen(arr)-1]=0;
                char *p2=buf+2;  //文件名
                strcpy(p2,arr);
                char *p4=p2+strlen(p2)+1;  //模式位
                strcpy(p4,"octet");
                int size=2+strlen(p2)+strlen(p4)+2; //请求包总长度
                //将请求包发送给服务器
                struct sockaddr_in sin;
                sin.sin_family=AF_INET;
                sin.sin_port=htons(SER_PORT);
                sin.sin_addr.s_addr=inet_addr(SER_IP);
                sendto(cfd,buf,size,0,(struct sockaddr*)&sin,sizeof(sin));
                printf("发送请求成功\n");
                unsigned short num=0;
                int fd=open(arr,O_RDONLY);
                ssize_t res=0;
                socklen_t addrlen = sizeof(sin);   //接受地址长度
                while(1)
                {
                    bzero(buf,sizeof(buf));
                    recvfrom(cfd,buf,4,0,(struct sockaddr*)&sin,&addrlen);
                    if(buf[1]==4)
                    {
                        if(*(unsigned short*)(buf+2)==htons(num))
                        {
                            buf[1]=3;
                            num++;
                            *(unsigned short*)(buf+2)=htons(num);
                            res=read(fd,buf+4,sizeof(buf)-4);
                            if(res==0)
                            {
                                break;
                            }
                            sendto(cfd,buf,sizeof(buf),0,(struct         
                            sockaddr*)&sin,sizeof(sin));
                        }
                    }
                }
                close(fd);
                printf("上传完毕\n");
            }break;
            case 3:goto END;
        }
    }
    END:
    close(cfd);
    return 0;
}

下载效果图

上传效果图

服务端

#include "talk.h"

int main(int argc, const char *argv[])
{
    int sfd;
    if ((sfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
    {
        perror("socket error");
    }
    printf("sfd=%d\n",sfd);
    struct sockaddr_in sin;
   bzero(&sin, sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = inet_addr(SER_IP);
    sin.sin_port = htons(SER_PORT);
    socklen_t sin_len = sizeof(sin);

    if (bind(sfd, (struct sockaddr *)&sin, sin_len) == -1)
    {
        perror("bind error");
    }
    struct sockaddr_in cin;
   bzero(&cin, sizeof(cin));
    socklen_t cin_len = sizeof(cin);
    msgTyp msg;
    //创建进程
    pid_t pid = fork();
    if (pid<0)
    {
        perror("fork error");
    }
    else if (pid == 0)
    {
        //子进程
        //接受数据并处理
        NodePtr L = NULL;
        list_create(&L);
        L->next = NULL;

        while (1)
        {
           bzero(&msg, sizeof(msg));
           bzero(&cin,  sizeof(cin));
            if ((recvfrom(sfd, &msg, sizeof(msg), 0, (struct sockaddr *)&cin, &cin_len)) == -1)
            {
                perror("recvfrom error");
            }
            printf("%s : %s\n", msg.name, msg.txt);
            switch (msg.code)
            {
            case 'L':
                denglu(sfd, msg, cin, L);
                break;
            case 'C':
                qunliao(sfd, msg, cin, L);
                break;
            case 'Q':
                tuichu(sfd, msg, cin, L);
                break;
            }
        }
    }
    else if (pid > 0)
    {
        //父进程
        //发系统消息
        msg.code='C';
        strcpy(msg.name,"server");
        while(1)
        {
            fgets(msg.txt,128,stdin);
            msg.txt[strlen(msg.txt)-1]='\0';
            if(sendto(sfd,&msg,sizeof(msgTyp),0,(struct sockaddr *)&sin,sin_len)==-1)
            {
                perror("sendto error");
            }
        }
    }
    close(sfd);
    return 0;
}

客户端

#include "talk.h"
//宏定义打印错误信息

int main(int argc, const char *argv[])
{
    //创建套接字
    int sfd;
    if ((sfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
    {
        perror("socket error");
    }
    //创建服务器网络信息结构体
    struct sockaddr_in sin;
    bzero(&sin,sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = inet_addr(SER_IP);
    sin.sin_port = htons(SER_PORT);
    socklen_t sin_len = sizeof(sin);
    //给服务器发送登录数据包
    msgTyp msg;
    bzero(&msg,sizeof(msgTyp));
    msg.code = 'L';
    printf("请输入用户名:");
    fgets(msg.name, 32, stdin);
    msg.name[strlen(msg.name) - 1] = '\0';

    strcpy(msg.txt, "加入群聊");
    if (sendto(sfd, &msg, sizeof(msgTyp), 0, (struct sockaddr *)&sin, sin_len) == -1)
    {
        perror("sendto error");
    }
    //创建父子进程
    pid_t pid;
    pid = fork();
    if (pid == -1)
    {
        perror("fork error");
    }
    else if (pid == 0)
    {
        //子进程
        //接受数据并处理
        while (1)
        {
            bzero(&msg, sizeof(msg));
            if (recvfrom(sfd, &msg, sizeof(msgTyp), 0, NULL, NULL) == -1)
            {
                perror("recvfrom error");
            }
            printf("%s:%s\n", msg.name, msg.txt);
        }
    }
    else if (pid > 0)
    {
        //父进程
        //发送消息
        while (1)
        {
            msg.code = 'C';
            fgets(msg.txt, 128, stdin);
            msg.txt[strlen(msg.txt) - 1] = '\0';
            if (strcmp(msg.txt, "quit") == 0)
            {
                msg.code = 'Q';
                strcpy(msg.txt, "退出群聊");
            }
            if (sendto(sfd, &msg, sizeof(msgTyp), 0, (struct sockaddr *)&sin, sin_len) == -1)
            {
                perror("sendto error");
            }
            if (strcmp(msg.txt, "退出群聊") == 0)
            {
                break;
            }
        }
        kill(pid,SIGKILL);
        wait(NULL);
        close(sfd);
    }
    return 0;
}

talk.c和talk.h

#include "talk.h"
//链表创建
void list_create(NodePtr*L)
{
    *L = (NodePtr)malloc(sizeof(Node));
}
//登录
int denglu(int sfd, msgTyp msg, struct sockaddr_in cin, NodePtr L)
{
    //遍历链表将登录信息发送给所以人
    NodePtr p = L;
    while (p->next != NULL)
    {
        p = p->next;
        if (sendto(sfd, &msg, sizeof(msgTyp), 0, (struct sockaddr *)&(p->c_addr), sizeof(p->c_addr)) == -1)
        {
            perror("recvfrom error");
        }
    }
    //头插
    NodePtr q = NULL;
    list_create(&q);
    q->c_addr = cin;
    q->next = L->next;
    L->next = q;
    return 0;
}

int qunliao(int sfd, msgTyp msg, struct sockaddr_in cin, NodePtr L)
{
    //遍历链表
    NodePtr p = L;
    while (p->next != NULL)
    {
        p = p->next;
        //判断链表是否是自己
        if (memcmp(&(p->c_addr), &cin, sizeof(cin)))
        {
            if (sendto(sfd, &msg, sizeof(msgTyp), 0, (struct sockaddr *)&(p->c_addr), sizeof(p->c_addr)) == -1)
            {
                perror("recvfrom error");
            }
        }
    }
    return 0;
}
//退出群聊
int tuichu(int sfd, msgTyp msg, struct sockaddr_in cin, NodePtr L)
{
    NodePtr p = L;

    while (p->next != NULL)
    {
        //判断链表是否是自己
        if (memcmp(&(p->next->c_addr), &cin, sizeof(cin)))
        {
            p = p->next;
            if (sendto(sfd, &msg, sizeof(msgTyp), 0, (struct sockaddr *)&(p->c_addr), sizeof(p->c_addr)) == -1)
            {
                perror("recvfrom error");
            }
        }
        else
        {
            NodePtr p = p->next;
            p->next = p->next;
            p->next = NULL;
            free(p);
            p = NULL;
        }
    }
    return 0;
}
#include <head.h>

typedef struct
{
    char code;
    char name[32];
    char txt[128];
} msgTyp;
//链表结构体
typedef struct Node
{
    struct sockaddr_in c_addr;
    struct Node* next;
} Node,*NodePtr;

//创建链表
void list_create(NodePtr*L);
//登录
int denglu(int sfd, msgTyp msg, struct sockaddr_in cin, NodePtr L);
//发送群消息
int qunliao(int sfd, msgTyp msg, struct sockaddr_in cin, NodePtr L);
//退出
int tuichu(int sfd, msgTyp msg, struct sockaddr_in cin, NodePtr L);

#define SER_PORT 9999
#define SER_IP "192.168.106.128"
#define CLI_PORT 6666
#define CLI_IP "192.168,106.128"

效果图

思维套图

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值