Linux系统下通过TCP可下载文件的客户端、服务端

来源:互联网 发布:java 二分法查找代码 编辑:程序博客网 时间:2024/06/14 00:29

这是运行与Linux系统下的多线程并发服务器,可供多个客服端下载普通文件,大型MP3/MP4等文件。

功能通过终端命令进行操作



client端代码:


#include  <netdb.h>#include <string.h>#include <stdlib.h>#include <errno.h>#include <sys/socket.h>#include <stdio.h>#include <sys/types.h>          /* See NOTES */#include <sys/stat.h>#include <fcntl.h>//./clt  ipint main(int argc, char ** argv){    int ret ;    int sfd;int fd;    char buf[1024] = {0};char filebuf[1024]={0};char buf1[20]={0};    sfd = socket(AF_INET, SOCK_STREAM, 0);    if(ret < 0) {        perror("socket");        return -1;    }    struct sockaddr_in  s_addr;    memset(&s_addr, 0, sizeof(s_addr));    s_addr.sin_family = AF_INET;    s_addr.sin_port = htons(8888);                    //服务器端口号,要转换成网络字节序    s_addr.sin_addr.s_addr  = inet_addr(argv[1]);     //服务器地址, 要转换成网络字节序    //连接服务器    ret = connect (sfd, (struct sockaddr *)&s_addr, sizeof(struct sockaddr));    if(ret < 0) {        perror("socket");        return -1;    }    char input[100];    while(1) {        printf("please input data:\r\n");        ret =  read(0, input, 50);        if(ret < 0) {            perror("send");            return -1;        }        input[ret-1] = '\0';        //发送数据给客户端        ret = send(sfd, input, strlen(input), 0);        if(ret < 0) {            perror("send");            return -1;        }memset(filebuf,0,sizeof(filebuf));strcat(filebuf,"./");strcat(filebuf,input);printf("%s\r\n",filebuf);fd = open(filebuf,  O_WRONLY | O_APPEND | O_CREAT, 0666);//if(fd<0){perror("open");}while(1){memset(buf,0,1024);        //接收数据,如果客户端没有发送数据会阻塞在这里        ret = recv(sfd, buf, 1024, 0);        if(ret < 0  ) {            perror("recv ");            return -1;        } if(ret == 0) {            printf("child thread tid==%lu exit\r\n", pthread_self());break;        }buf[ret]='\0';if(memcmp(buf,"ok",2)==0){printf("------download finshed----\r\n");break;}write(fd, buf, 1024);memset(buf,0,1024);}close(fd);    }    close(sfd);    return 0;}

service端带代码:

//多线程并发服务器#include  <netdb.h>#include <string.h>#include <stdlib.h>#include <errno.h>#include <sys/socket.h>#include <stdio.h>#include <sys/types.h>          /* See NOTES */#include <pthread.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>struct server_info {    int cfd;                         //通信套接字    struct sockaddr_in     c_addr;   //存放客户端地址};void * function(void*arg)   ;int main(int argc, char ** argv){    int ret ;    int sfd, cfd;    pthread_t  tid;  //线程id    sfd = socket(AF_INET, SOCK_STREAM, 0);    if(ret < 0) {        perror("socket");        return -1;    }    //让服务器断开后重启连接不会报地址被占用的错误    int reuse = 1;    ret = setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));    struct sockaddr_in  s_addr;    memset(&s_addr, 0, sizeof(s_addr));    s_addr.sin_family = AF_INET;    s_addr.sin_port = htons(8888);                    //服务器端口号,要转换成网络字节序    //s_addr.sin_addr.s_addr =  inet_addr("192.168.1.123");//服务器地址, 要转换成网络字节序    s_addr.sin_addr.s_addr  =  0;    //服务器一般填充0,这样程序可以任意IP的计算中运行。    ret  =  bind(sfd, ( struct sockaddr*)&s_addr, sizeof(struct sockaddr));    if(ret < 0) {        perror("bind");        return -1;    }    ret = listen(sfd, 10);    if(ret < 0) {        perror("listen");        return -1;    }    struct sockaddr_in  c_addr;    int  addrlen;    memset(&c_addr, 0, sizeof(c_addr));    while(1) {        //等待连接        cfd = accept(sfd, (struct sockaddr*)&c_addr, &addrlen);        if(cfd < 0) {            perror("accept ");            return -1;        }        //创建线程独立数据结构空间        //每个线程应该有独立的cfd,c_add结构,malloc是在堆空间中分配数据        struct server_info *tinfo = malloc(sizeof(struct server_info));        memset(tinfo, 0, sizeof( struct server_info));        tinfo->cfd    = cfd;        tinfo->c_addr = c_addr;        ret = pthread_create(&tid, NULL, function, (void*)tinfo) ; //创建线程        if(ret != 0) {            perror("pthread_create ");            free(tinfo);            return -1;        }    }    close(sfd);    return 0;}//写一个线程函数//假设传递进来是 struct server_info * ,则把arg转换回来void * function(void*arg){    int ret;int fd;int fr;    char buf[1025] = {0};char filebuf[1024]={0};char fbuf[]={"ok"};//int fbuf[1]={52};    struct server_info * info = ( struct server_info *)arg;    pthread_detach(pthread_self());       //把本线程变成分离式线程    //char *inet_ntoa(struct in_addr in);    printf("One client is connected:ip:%s:%d\r\n",           inet_ntoa(info->c_addr.sin_addr), ntohs(info->c_addr.sin_port));    while(1) {        //接收数据,如果客户端没有发送数据会阻塞在这里        printf("=========\r\n");        ret = recv(info->cfd, buf, 100, 0);        if(ret < 0) {            perror("recv ");            break;        }        //ret==0;说明连接已经断开,子进程 要终止        if(ret == 0) {            printf("child thread tid==%lu exit\r\n", pthread_self());            //资源释放            close(info->cfd);            free(info);                        pthread_exit(NULL);        }       buf[ret] = '\0';        printf("C---> S : %s \r\n", buf);memset(filebuf,0,sizeof(filebuf));strcat(filebuf,"./");strcat(filebuf,buf);//strcat(filebuf,".mp3");//strcat(filebuf,".txt");printf("%s\r\n",filebuf);fd = open(filebuf,  O_RDONLY);if(fd<0){perror("open");}while(1){memset(buf,0,1024);fr=read(fd, buf, 1024);if(fr==0){printf("file read over\r\n");sleep(1);//不加延时会不能跳出来ret = send(info->cfd, fbuf, 2, 0);//printf("%d\r\n",strlen(fbuf));        if(ret < 0) {            perror("send");            break;        }break;        }else {//发送数据给客户端        ret = send(info->cfd, buf, fr, 0);        if(ret < 0) {            perror("send");            break;        }}}//perror("open------------------");close(fd);    }    //资源释放    close(info->cfd);    free(info);    pthread_exit(NULL);}

阅读全文
0 0