作业-11.24

1、多线程并发服务器

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

#define ERRLOG(msg) do{\
                printf("%s:%s:%d\n", __FILE__, __func__, __LINE__);\
                perror(msg);\
            }while(0)

#define N 128

typedef struct _MSG{
    int acceptfd;
    struct sockaddr_in clientaddr;
}msg_t;

void *deal_read_write(void *arg)
{
    msg_t msg = *(msg_t *)arg;
    printf("客户端[%s:%d]连接到服务器..\n", inet_ntoa(msg.clientaddr.sin_addr), ntohs(msg.clientaddr.sin_port));
    int nbytes = 0;
    char buff[N] = {0};
    while(1)
    {
        memset(buff, 0, N);
        if(-1 == (nbytes = recv(msg.acceptfd, buff, N, 0)))
        {
            perror("recv");
            break;
        }
        else if(!nbytes)
        {
            printf("客户端[%s:%d]断开了连接..\n", inet_ntoa(msg.clientaddr.sin_addr), ntohs(msg.clientaddr.sin_port));
            break;
        }
        if(!strncmp(buff, "quit", 4))
        {
            printf("客户端[%s:%d]退出了..\n", inet_ntoa(msg.clientaddr.sin_addr), ntohs(msg.clientaddr.sin_port));
            break;
        }
        printf("客户端[%s:%d]发来数据[%s]\n", inet_ntoa(msg.clientaddr.sin_addr), ntohs(msg.clientaddr.sin_port), buff);
        strcat(buff, "-->\n");
        if(-1 == send(msg.acceptfd, buff, N, 0))
        {
            perror("send");
           break;
        }
    }
    close(msg.acceptfd);
    pthread_exit(NULL);
}

int main(int argc, const char *argv[])
{
    if(3 != argc)
    {
        printf("Usage : %s <IP> <port>\n", argv[0]);
        exit(-1);
    }

    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if(-1 == sockfd)
    {
        ERRLOG("socket");
        return -1;
    }

    struct sockaddr_in serveraddr;
    memset(&serveraddr, 0, sizeof(serveraddr));
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
    serveraddr.sin_port = htons(atoi(argv[2]));

    socklen_t serveraddr_len = sizeof(serveraddr);

    if(-1 == bind(sockfd, (struct sockaddr *)&serveraddr, serveraddr_len))
    {
        ERRLOG("bind");
        return -1;
    }

    if(-1 == listen(sockfd, 5))
    {
        ERRLOG("listen");
        return -1;
    }

    struct sockaddr_in clientaddr;
    memset(&clientaddr, 0, sizeof(clientaddr));
    socklen_t clientaddr_len = sizeof(clientaddr);

    int acceptfd = 0;
    pthread_t tid = 0;
    msg_t msg;
     int err_code = 0;

    while(1)
    {
        if(-1 == (acceptfd = accept(sockfd, (struct sockaddr *)&clientaddr, &clientaddr_len)))
        {
            ERRLOG("accept");
            return -1;
        }
        msg.acceptfd = acceptfd;
        msg.clientaddr = clientaddr;
        if(0 != (err_code  = pthread_create(&tid, NULL, deal_read_write, &msg)))
        {
            printf("pthread_create error %s\n", strerror(err_code));
            return -1;
      }
        if(0 !=  (err_code = pthread_detach(tid)))
        {
            printf("pthread_detach error %s\n", strerror(err_code));
            return -1;
      }
    }

    close(sockfd);

    return 0;
}

 

2、多进程并发服务器

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

#define ERRLOG(msg) do{\
                printf("%s:%s:%d\n", __FILE__, __func__, __LINE__);\
                perror(msg);\
            }while(0)

#define N 128

void sig_function()
{
    wait(NULL);
}

int main(int argc, const char *argv[])
{
    if(3 != argc)
    {
        printf("Usage : %s <IP> <port>\n", argv[0]);
        return -1;
    }

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

    struct sockaddr_in serveraddr;
    memset(&serveraddr, 0, sizeof(serveraddr));
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
    serveraddr.sin_port = htons(atoi(argv[2]));

    socklen_t serveraddr_len = sizeof(serveraddr);

    if(bind(sockfd, (struct sockaddr *)&serveraddr, serveraddr_len) < 0)
    {
        ERRLOG("bind");
        return -1;
    }

    if(listen(sockfd, 5) < 0)
    {
        ERRLOG("listen");
        return -1;
    }

    signal(SIGUSR1, sig_function);

    struct sockaddr_in clientaddr;
    memset(&clientaddr, 0, sizeof(clientaddr));
    socklen_t clientaddr_len = sizeof(clientaddr);

    int acceptfd = 0;
    pid_t pid = 0;

    while(1)
    {
        if((acceptfd = accept(sockfd, (struct sockaddr *)&clientaddr, &clientaddr_len)) < 0)
        {
            ERRLOG("accept");
            return -1;
        }

        if((pid = fork()) < 0)
        {
            ERRLOG("fork");
            return -1;
        }
        else if(!pid)
        {
            printf("客户端[%s:%d]连接到服务器..\n", inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port));
            int nbytes = 0;
            char buff[N] = {0};
            while(1)
            {
                memset(buff, 0, N);
                if((nbytes = recv(acceptfd, buff, N, 0)) < 0)
                {
                    ERRLOG("recv");
                    return -1;
                }
                else if(!nbytes)
                {
                    printf("客户端[%s:%d]断开了连接..\n", inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port));
                    break;
                }
                if(!strncmp(buff, "quit", 4))
                {
                    printf("客户端[%s:%d]退出了..\n", inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port));
                    break;
                }
                printf("客户端[%s:%d]发来数据[%s]\n", inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port), buff);
                strcat(buff, "--hqyj");
                if(send(acceptfd, buff, N, 0) < 0)
                {
                    ERRLOG("send");
                    return -1;
                }
            }
            close(acceptfd);
            kill(getppid(), SIGUSR1);
            return 0;
        }
        else if(pid > 0)
        {
            close(acceptfd);
        }
    }

    close(sockfd);

    return 0;
}

 

 

3、fttp下载上传

#include <stdio.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>

#define ERR_MSG(msg) do{\
    fprintf(stderr, "__%d__:", __LINE__);\
    perror(msg);\
}while(0)

int do_download(int sfd, struct sockaddr_in sin);
int do_upload(int sfd, struct sockaddr_in sin);

int main(int argc, const char *argv[])
{
    if(argc != 3)
    {
        printf("please--> %s <IP> <PORT>\n", argv[0]);
        return -1;
    }

    int sfd = socket(AF_INET, SOCK_DGRAM, 0);
    if(sfd < 0)
    {
        ERR_MSG("socket");
        return -1;
    }

    struct sockaddr_in sin;
    sin.sin_family      = AF_INET;      
    sin.sin_port        = htons(atoi(argv[2]));  
    sin.sin_addr.s_addr = inet_addr(argv[1]);

    char c = 0;
    int flag = 1;
    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':
            do_download(sfd, sin);
            break;
        case '2':
            do_upload(sfd, sin);
            break;
        case '3':
            flag = 0;
            break;
        default:
            printf("输入错误,请重新输入\n");
        }

        if(!flag)
        {
            break;
        }
        printf("输入任意字符清屏>>>");
        while(getchar() !=10);
    }


    close(sfd);
    return 0;
}

int do_download(int sfd, struct sockaddr_in sin)
{
    char filename[20] = "";
    char buf[516] = "";

    bzero(buf, sizeof(buf));
    printf("请输入要下载的文件名>>>");
    fgets(filename, sizeof(filename), stdin);
    filename[strlen(filename)-1] = 0;

    int size = sprintf(buf, "%c%c%s%c%s%c", 0, 1, filename, 0, "octet", 0);
    if(sendto(sfd, buf, size, 0, (struct sockaddr*)&sin, sizeof(sin)) < 0)
    {
        ERR_MSG("sendto");
        return -1;
    }

    int fd = -1, flag = 0;    
    socklen_t addrlen = sizeof(sin);
    ssize_t res = 0;

    unsigned short num = 0;     

    while(1)
    {
        bzero(buf, sizeof(buf));
        res = recvfrom(sfd, buf, sizeof(buf), 0, (struct sockaddr*)&sin, &addrlen);
        if(res < 0)
        {
            ERR_MSG("recvfrom");
            return -1;
        }

        if(3 == buf[1])
        {
            if(htons(num+1) == *(unsigned short*)(buf+2))
            {
                num++;

                if(0 == flag)
                {
                    fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0664);
                    if(fd < 0)
                    {
                        ERR_MSG("open");
                        return -1;
                    }
                    flag = 1;
                }

                if(write(fd, buf+4, res-2-2) < 0)
                {
                    ERR_MSG("write");
                    return -1;
                }

                buf[1] = 4;
                if(sendto(sfd, buf, 4, 0, (struct sockaddr*)&sin, sizeof(sin)) < 0)
                {
                    ERR_MSG("sendto");
                    return -1;
                }

                if(res-2-2 < 512)
                {
                    printf("%s 文件下载完毕\n", filename);
                    break;
                }
            }
        }
        else if(5 == buf[1])
        {
            fprintf(stderr, "错误码:%d 错误信息:%s\n", ntohs(*(unsigned short*)(buf+2)), buf+4);
            break;
        }
    }

    close(fd);
    return 0;
}

int do_upload(int sfd, struct sockaddr_in sin)
{
    char str[1000] = "";
    char *ptr = str;
    short int *ptr1 = (short int*)ptr;
    *ptr1 = htons(2);
    char *ptr2 = ptr+2;

    char filename[128] = "";
    printf("请输入要上传的文件名>>>");
    scanf("%s",filename);
    getchar();
    strcpy(ptr2,filename);

    char *ptr3 = ptr2+strlen(ptr2)+1;
    strcpy(ptr3,"octet");

    int size = 2+strlen(ptr2)+1+strlen(ptr3)+1;
    if(sendto(sfd, str, size, 0, (struct sockaddr*)&sin, sizeof(sin)) < 0)
    {
        ERR_MSG("sendto");
        return -1;
    }
    printf("sendto success\n");

    char str1[6] = "";                  
    struct sockaddr_in rcv_addrmsg;
    socklen_t addrlen = sizeof(rcv_addrmsg);


    if(recvfrom(sfd,str1,sizeof(str1),0,(struct sockaddr*)&rcv_addrmsg,&addrlen) < 0)
    {
        ERR_MSG("recvfrom");
        return -1;
    }

    int fd = open(filename,O_RDONLY);
    if(fd<0)
    {
        ERR_MSG("open");
        return -1;
    }

    short int num = 1;                       
    char str2[1024] = "";


    ssize_t rts = 0;
    while(1)
    {
        char *sjb = str2;
        short int *sjb1 = (short int*)sjb;
        *sjb1 = htons(3);

        short int *sjb2 = (short int*)(sjb+2);
        *sjb2 = htons(num);

        char *sjb3 = (str2+4);

        rts = read(fd,sjb3,512);
        int sjblen = rts+4;

        if(sendto(sfd,str2,sjblen,0,(struct sockaddr*)&rcv_addrmsg,addrlen) < 0)
        {
            ERR_MSG("sendto");
            return -1;
        }

        bzero(str1,sizeof(str1));
        if(recvfrom(sfd,str1,sizeof(str1),0,(struct sockaddr*)&rcv_addrmsg,&addrlen) < 0)
        {
            ERR_MSG("recvfrom");
            return -1;
        }

        char *ack = str1;
        short int *err;
        err = (short int*)ack;
        if(ntohs(*err) == 5)
        {
            printf("error:%s\n",(char*)(err+2));
            return -1;
        }

        short int *kbh = (short int*)str1;
        if(ntohs(*(kbh+1)) != num)
        {
            continue;
        }

        num++;

        if(rts != 512)
        {
            printf("send file success!\n");
            break;
        }

    }
}

        下载

 

        上传

                上传前

                 上传后

                 终端

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值