linux C语言TCP协议实现镜像服务器,并发服务器,文件传输

镜像服务器 返回连接者的ip端口回去:

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

int main(int argc, char const *argv[])
{
    //1.创建服务器socket
    int tcp_socket = socket(AF_INET, SOCK_STREAM, 0);

    //2.绑定IP地址信息
    struct sockaddr_in ser_addr;
    ser_addr.sin_family = AF_INET;//IPV4
    ser_addr.sin_port = htons(6667) ;//采用大端序
    ser_addr.sin_addr.s_addr = INADDR_ANY;//自动绑定本地网卡地址

     int ret = bind(tcp_socket,(struct sockaddr *)&ser_addr, sizeof(ser_addr));
     if(ret < 0)
     {
        perror("");
     }else{
        printf("绑定成功!\n");
     } 
     //3.设置为监听模式
     listen(tcp_socket,5);

     //4.接收客户端链接
     while (1)
     {
        struct sockaddr_in clien_addr;//保存对方的IP地址信息
        int len = sizeof(struct sockaddr_in);

        int new_socket = accept(tcp_socket, (struct sockaddr *)&clien_addr, &len);
       

        if(new_socket > 0)
        {
            char *ip = inet_ntoa(clien_addr.sin_addr);  
            //提取端口
            unsigned short port = ntohs(clien_addr.sin_port);     

                char bufip[1024] = {0};       
                sprintf(bufip , "%s:%d",ip, port);
                printf("%s:%d",ip,port);
                write(new_socket,bufip,strlen(bufip));
        }

     }
            

    return 0;
}

利用TCP 传输协议实现 文件的传输功能

 

 服务器接收文件代码:

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

int main(int argc, char const *argv[])
{
    //1.创建服务器socket
    int tcp_socket = socket(AF_INET, SOCK_STREAM, 0);

    //2.绑定IP地址信息
    struct sockaddr_in ser_addr;
    ser_addr.sin_family = AF_INET;//IPV4
    ser_addr.sin_port = htons(6667) ;//采用大端序
    ser_addr.sin_addr.s_addr = INADDR_ANY;//自动绑定本地网卡地址

     int ret = bind(tcp_socket,(struct sockaddr *)&ser_addr, sizeof(ser_addr));
     if(ret < 0)
     {
        perror("");
        return -1; 
     }else{
        printf("绑定成功!\n");
     } 
     //3.设置为监听模式
     listen(tcp_socket,5);

     //4.接收客户端链接
     while (1)
     {

        printf("等待客户端发送文件\n");
        int new_socket = accept(tcp_socket, NULL,NULL);
       

        if(new_socket > 0)
        {
            printf("开始接收。。。\n");
             //接收文件名+文件大小 
            char file_msg[1024];//file 文件名 文件大小
            read(new_socket,file_msg,1024);


             //获取文件名和文件大小             
            char file_name[1024];
            int file_size ;
            if(strstr(file_msg, "file"))
            {
             sscanf(file_msg, "file %s %d",file_name, &file_size);
            }else{
                printf("解析文件失败\n");
                close(new_socket);
                  continue;
            }

            printf("对方发送的文件名:%s 文件大小%d\n",file_name,file_size);

            //告诉发送端,已经得到了文件的信息   
            write(new_socket,"GOGOGO", strlen("GOGOGO"));

            //创建文件
            int fd = open("./2.jpg", O_RDWR|O_CREAT|O_TRUNC,0777);
            //下载大小  
            int dow_size = 0;
            //不断接收数据 
            while (1)
            {
                 //读取网络数据
                char data[4096] = {0};
                int size = read(new_socket,data,4096);
                dow_size += size;

                //写入本地文件
                write(fd,data,size);

                //判断是否下载完毕
                if(dow_size >= file_size)
                {
                    printf("下载完毕\n");

                    //告诉发送端以及下载完毕 可以断开连接
                    write(new_socket, "down_ok",strlen("down_ok"));
                    close(fd);
                    close(new_socket);

                    break;
                }else{
                    printf("下载进度:%d %%\n", dow_size*100/file_size);
                }

            }
            

        }

     }
            
    return 0;
}

客户端发送文件代码:

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

int main(int argc, char const *argv[])
{
    if(argc < 2)
    {
        printf("请输入发送的文件\n");
        return -1;
    }
    //发送文件名与大小给服务器  file 文件名 文件大小
    int fd = open(argv[1],O_RDWR);
    if(fd < 0)
    {
        perror("");
        return -1;
    }

    //1.创建服务器socket
    int tcp_socket = socket(AF_INET, SOCK_STREAM, 0);

    //2.设置服务器信息
    struct sockaddr_in ser_addr;
    ser_addr.sin_family = AF_INET;//IPV4
    ser_addr.sin_port = htons(6667) ;//采用大端序
    ser_addr.sin_addr.s_addr = inet_addr("192.168.202.128");//自动绑定本地网卡地址

    //链接服务器
     int ret = connect(tcp_socket,(struct sockaddr *)&ser_addr, sizeof(ser_addr));
     if(ret < 0)
     {
        perror("");
         return -1; 
     }else{
        printf("链接服务器成功!\n");
     }
     //获取文件大小
     struct stat file_size;
     stat(argv[1], &file_size);

     char file_msg[1024] = {0};

     //拼接协议
     sprintf(file_msg, "file %s %ld",argv[1], file_size.st_size);

     //发送给服务器
     write(tcp_socket, file_msg, strlen(file_msg));

     //等待服务器应答
     char rec[1024] = {0};
     read(tcp_socket, rec, 1024);
     printf("rec%s\n",rec);
     if(strcmp(rec,"GOGOGO") == 0)
     {
        while (1)
        {
            char data[4096] = {0};
            int size = read(fd, data, 4096);
            if(size <= 0 )
            {
                printf("读取完毕\n");
                break;
            }

            write(tcp_socket,data, size);
        }
        
     }

     //等待服务器接收完毕
     bzero(rec,1024);
    read(tcp_socket,rec,1024); 

    if(strcmp(rec,"down_ok") == 0)
    {
         printf("关闭所有链接\n");
         close(tcp_socket);
         close(fd); 
    }
            
    return 0;
}

结果:

利用TCP 传输协议实现 与多个客户端通信功能:并发服务器

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

struct node *head;

//设计单链表的节点 
struct  node 
{
    char data[1024]; 
    int fd;
    struct  node *next;  
};


//尾插入
struct node * Tail_InserNode (struct node *head , char * Dat, int fd)
{
    //新建节点
    struct node * Newnode = malloc(sizeof(struct node));

    //指向头节点
    struct node * pos = head;

        while (pos->next != NULL)  //为什么不写 while (pos != NULL)  pos != NULL 循环结束后,pos 已经指向NULL 
        pos =pos ->next;

        //初始化新节点  
        strcpy(Newnode->data,Dat);
        Newnode->fd = fd;
        Newnode ->next = NULL;

        //插入新节点
        pos->next = Newnode;

        return Newnode;
}

//遍历节点
void TraverseNodes(struct node *head)
{
    //1.指向链表中的第一个节点 
    struct node *pos = head->next; 

    while (pos != NULL)
    {
        printf("pos->data=%s\n",pos->data);

        pos = pos->next;
    }

    printf("__________华丽的分割线_______________\n");
}

//查找节点 
int  FindNodes(struct node *head,char *find_data)
{
    
    //1.遍历链表 
    struct node *pos = head->next; 

    while (pos != NULL)
    {
        //判断是否为需要查找的数据 
        if(strcmp(pos->data,find_data))
        {
            printf("找到数据 %s\n",pos->data);

            return pos->fd; 
        }
         
         pos = pos->next;
    }
    
    printf("查无此数据\n");
    return -1;
}

//删除节点 
void DeleteNode(struct node *head,char *del_data)
{
      
    struct node *pos =  head->next; 

    struct node *prev = head; //永远都指向pos的之前一个 

    //1.遍历链表找到需要删除的数据 
    while (pos != NULL)
    {
        if(strcmp(pos->data,del_data)) //找到需要删除的数据
        {
            //printf("找到删除的数据\n");

            //重新连线 
            prev->next = pos->next; 

            pos->next = NULL; 

            free(pos); //释放节点

            //回家 
            pos = prev;

        }

        prev= pos; //在pos偏移前,保存他的前一个位置 
        pos = pos->next; //不断偏移 
    }
}


//控制服务器任务 
void *ctrl_task(void *arg)
{
    while (1)
    {
        printf("1.查看在线用户   2.发送信息 3.退出服务器\n");
        int n =0; 
        scanf("%d",&n);


        if(n == 1)
        {
            struct  people *pos=NULL;
            TraverseNodes(head);
        }

        if(n == 2)
        {

            printf("请输入 IP 消息\n");
            char ip[50]={0}; 
            char msg[100]={0}; 
            scanf("%s",ip);
            scanf("%s",msg); 

            //找到对应的SOCKET  
            struct  people *pos=NULL;
            int socket= FindNodes(head, ip);

            write(socket,msg,strlen(msg));

            
        }
    }
}


//读取任务 
void *read_task(void *arg)
{
    struct node *node = (struct node *)arg;

    char msg[1024]={0};
    while (1)
    {
        bzero(msg,1024); 
        int s=read(node->fd,msg,1024);
        if(s > 0)
        {
            printf("IP:%s msg:%s\n",node->data,msg);
        }else 
        {
            printf("IP:%s 离线\n",node->data);

            //关闭描述符 
            close(node->fd); 

            //删除节点 
            DeleteNode(head,node->data);

            break;
        }
    }
    
    pthread_exit(NULL); //退出线程
}

int main(int argc, char const *argv[])
{
    //1.创建头节点 
    head = malloc(sizeof(struct node)); 
    //初始化头节点
    strcpy(head->data,"");
    head->next = NULL;

    //1.创建TCP服务器对象 
    int tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
    if(tcp_socket < 0)
    {
        perror("");
    }else{

        printf("tcp通信对象创建成功!\n");
    }

    //2.绑定IP地址信息
    struct sockaddr_in ser_addr;
    ser_addr.sin_family = AF_INET;//IPV4
    ser_addr.sin_port = htons(6667) ;//采用大端序
    ser_addr.sin_addr.s_addr = INADDR_ANY;//自动绑定本地网卡地址

     int ret = bind(tcp_socket,(struct sockaddr *)&ser_addr, sizeof(ser_addr));

     if(ret < 0)
     {
        perror("");
     }else{
        printf("绑定成功!\n");
     }

     //创建一个服务器控制线程
    pthread_t ctrl_tid;
    pthread_create(&ctrl_tid,NULL,ctrl_task,NULL);


     //3.设置为监听模式
     ret = listen(tcp_socket,5);
     if(ret < 0)
     {
        perror("");
     }else{
        printf("监听成功!\n");
     }

     printf("等待客户端链接。。。\n");

//接收链接客户端
while (1)
{
    struct sockaddr_in clien_addr;
    socklen_t addrlen = sizeof(clien_addr);
    int new_socket = accept(tcp_socket,(struct sockaddr *)&clien_addr,&addrlen);

     if(new_socket<0)
     {
        perror("");        
     }else{
        printf("接收链接成功:%d\n",new_socket);
     }

    //提取ip
     char *ip = inet_ntoa(clien_addr.sin_addr);   
    //提取端口
    unsigned short port = ntohs(clien_addr.sin_port);

     printf("链接着ip:%s 端口:%d\n", ip, port);
     char bufip[1024] = {0};
     sprintf(bufip , "%s:%d",ip, port);
     printf("%s:%d",ip,port);

    struct  node *new_node = Tail_InserNode(head,bufip,new_socket);
        pthread_t tid;
    pthread_create(&tid, NULL, read_task, new_node);
}

            //关闭通信 
    //close(new_socket);  
    return 0;
}

利用TCP 传输协议实现 中转服务器

#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <pthread.h>

//添加内核链表头文件 
#include "list.h"
 
//设计在线链表 
struct  people
{
   char ip[50];  //IP 
   unsigned short port; //端口
   int socket; //描述符
   char name[50];//名称 
    //添加内核链表
   struct list_head list; 
};

struct list_head *head=NULL;

//控制服务器任务 
void *ctrl_task(void *arg)
{
    while (1)
    {
        printf("1.查看在线用户 3.退出服务器\n");
        int n =0; 
        scanf("%d",&n);

        if(n == 1)
        {
            struct  people *pos=NULL;
            list_for_each_entry(pos,head,list) //遍历链表获取在线用户信息 
            {
                printf("name:%s socket:%d ip:%s port:%d\n",pos->name,pos->socket,pos->ip,pos->port);
            }
        }

      
    }
}

//读取任务 
void *read_task(void *arg)
{
    struct  people *xnew = arg; 

    char msg[1024]={0};
    while (1)
    {
        bzero(msg,1024); 
        int s=read(xnew->socket,msg,1024);
        if(s > 0)
        {
            printf("名称:%s msg:%s\n",xnew->name,msg);

            //进行转发   msg  名称 消息 
            if(msg[0]='m' && msg[1] == 's' && msg[2] == 'g')
            {
                printf("开始转发\n");
                char  name[50]={0};
                char  send_msg[100]={0}; 
                char  h[50]={0};
                sscanf(msg,"%s %s %s",h,name,send_msg);

                printf("name=%s\n",name);

                //找到需要接收数据的socket 
                struct  people *pos=NULL;
                list_for_each_entry(pos,head,list) //遍历链表获取在线用户信息 
                {    
                     if(strcmp(pos->name,name) == 0)
                     {
                         printf("转发成功\n");
                         write(pos->socket,send_msg,strlen(send_msg)); //转发 
                         break;
                     }
                }
            }
        }else 
        {
            printf("IP:%s 离线\n",xnew->ip);

            //关闭描述符 
            close(xnew->socket); 

            //删除节点 
            list_del(&xnew->list);

            //释放节点
            free(xnew);

            break;
        }
    }
    
    pthread_exit(NULL); //退出线程
}




int  main()
{
    //初始化内核链表 
    head = malloc(sizeof( struct list_head)); 
    INIT_LIST_HEAD(head);


    //1.创建服务器socket 
    int   tcp_socket = socket(AF_INET, SOCK_STREAM, 0);


    //2.绑定服务器信息  
     struct sockaddr_in   addr; 
      addr.sin_family = AF_INET; //ipv4 
      addr.sin_port   = htons(6665);//端口为 6666
      addr.sin_addr.s_addr = INADDR_ANY; //本地所有网卡地址
   int ret=bind(tcp_socket,(struct sockaddr *)&addr,sizeof(addr));
       if(ret < 0)
       {
            perror("绑定失败\n");
            return -1; 
       }


    //创建一个服务器控制线程
    pthread_t ctrl_tid;
    pthread_create(&ctrl_tid,NULL,ctrl_task,NULL);

    //3.设置为监听模式 
        listen(tcp_socket,5);

        //接收客户端的链接请求并添加到链表中
        while (1)
        {
              //新建节点 
              struct people *xnew=malloc(sizeof(struct  people));


               struct sockaddr_in clien_addr; //保存对方的IP地址信息 
               int len = sizeof(struct sockaddr);


            xnew->socket = accept(tcp_socket,(struct sockaddr *)&clien_addr,&len);
                if( xnew->socket > 0) //连接成功 
                {
                    printf("新的客户端链接 %d 等待注册\n",xnew->socket);

                    //告诉客户端需要注册设备名 
                    write(xnew->socket,"reg_name",strlen("reg_name"));

                    //读取设备名
                    char  reg_name[1024]={0}; 
                    read(xnew->socket,reg_name,1024);    //超时检测
                    if(strstr(reg_name,"name"))
                    {
                        printf("设备注册成功\n");
                        //初始化其他信息 
                        xnew->port = ntohs(clien_addr.sin_port);
                        strcpy(xnew->ip,inet_ntoa(clien_addr.sin_addr));
                        sscanf(reg_name,"name %s",xnew->name); 
                     
                        //插入节点 
                        list_add_tail(&xnew->list,head);

                        //开启线程 
                        pthread_t tid; 
                        pthread_create(&tid,NULL,read_task,xnew);
                        pthread_detach(tid);
                    }else 
                    {
                        close(xnew->socket); 

                        free(xnew);
                    }
                }
                else
                {
                    perror("");
                    free(xnew);
                }
        }

}

猜你喜欢

转载自blog.csdn.net/aaa2540567665/article/details/126413783