Linux C Socket局域网文件互传

本人刚接触c/c++不是特别久,所以很多地方的写法可能会比较蠢和复杂化,思路也不是特别明确,各位请见谅..

代码是在安卓手机软件"C4droid"上开发运行的,运行环境是linux.

程序即是客户端也是服务端,第一次使用先定义自己的用户名,用户名保存在本地文件中.

可以拿两部手机来测试,进入程序后,先输入'1'进行局域网嗅探在线的用户,时间可能比较久。watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAYTQ0NjQ1,size_20,color_FFFFFF,t_70,g_se,x_16

 

然后输入2文件传输,再输入需要配对用户的id即可进行传输.watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAYTQ0NjQ1,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAYTQ0NjQ1,size_20,color_FFFFFF,t_70,g_se,x_16 

 另一台手机watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAYTQ0NjQ1,size_20,color_FFFFFF,t_70,g_se,x_16

 

 

 

代码:

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <pthread.h>

#include <time.h>

#include <cstdlib>

#include <iostream>

#include <pthread.h>

#include <vector>

#define CONFIG "/sdcard/Server/.config"

#define FULL_LEN 524288

#define TIMEOUT 1

char User_Name[32];

char YN = 'O';

int ipv4 = 0;

bool istrans = false;

typedef struct sockaddr zhang;

struct MSG_STRUCT
{
    char msg[512] = "";
    char User_Name[32] = "";
    float File_Len = 0;
};

struct IP_STRUCT
{
    char IP[32] = "";
    char buf[512] = "";
    char User_Name[32] = "";
    int id = 0;
    int PORT = 0;
    int ip[3];
    int Cli_fd = 0;
    int Ser_fd = 0;
    bool is_ip = false;
    bool connected = false;
};

struct File_Data
{
    char Path[512];

    char buf[FULL_LEN];

    char File_Name[64];

    bool success = false;

    float size = 0;
};

size_t GetFileSize(const char *Path)
{
    FILE *READ = fopen(Path, "r");

    if (READ == NULL)
    {
        fclose(READ);
        return -1;
    }
    else
    {
        fseek(READ, 0, SEEK_END);
        int len = ftell(READ);
        fclose(READ);
        return len;
    }
}

void *Send_Data(void *ff, void *bu)
{
    File_Data *r = (struct File_Data *)bu;

    int fd = *(int *)ff;

    FILE *Path = fopen(r->Path, "r");

    bzero(r->buf, sizeof(r->buf));

    int n = 0;
    while (n = fread(r->buf, sizeof(char), FULL_LEN, Path))
    {
        if (send(fd, r->buf, n, 0) < 0)
        {
            r->success = false;
            break;
        }

        bzero(r->buf, sizeof(r->buf));
    }

    puts("成功发送");
    close(fd);
    r->success = true;
    fclose(Path);
}

void *Recv_Data(void *ff, void *bu)
{
    File_Data *r = (struct File_Data *)bu;

    int fd = *(int *)ff;

    std::string str = r->Path;
    int offset = str.rfind("/");
    str.erase(0, offset);
    strcpy(r->File_Name, str.c_str());

    char *TempStr = new char[256];
    sprintf(TempStr, "/sdcard/Server/%s", r->File_Name);
    FILE *Path = fopen(TempStr, "w+");

    bzero(r->buf, sizeof(r->buf));

    int n = 0, count = 0;
    while (n = recv(fd, r->buf, FULL_LEN, 0))
    {
         
        if (n < 0)
            break;

        if (fwrite(r->buf, sizeof(char), n, Path) < n)
        {
            printf("Failed!\n");
            r->success = false;
            break;
        }
        
        count += n;

        bzero(r->buf, sizeof(r->buf));
    }

    printf("文件接收完毕,大小%fMB\n", (float)count / 1024.0 / 1024.0);
    close(fd);
    r->success = true;
    fclose(Path);
    free(TempStr);
    istrans = false;
}

void *User_thread(void *p)
{
    int fd = *(int *)p;
    while (true)
    {
        char buf[sizeof(MSG_STRUCT)];
        if (recv(fd, buf, sizeof(buf), 0) > 0)
        {
            MSG_STRUCT Msg = *(struct MSG_STRUCT *)buf;
            if (strcmp(Msg.msg, "INIT_OK") == 0)
            {
                send(fd, User_Name, sizeof(User_Name), 0);
            }

            if (strcmp(Msg.msg, "FILE_TRANS") == 0)
            {
                printf("%s向你发了一个%fMB的文件,是否接收?\n", Msg.User_Name,
                       Msg.File_Len);
              Again:
                puts("请输入Y/N");
                
                while (YN == 'O');
                if (YN == 'Y')
                {
                    YN = 'O';
                    send(fd, "Y", sizeof("N"), 0);
                }
                else if (YN == 'N')
                {
                    YN = 'O';
                    send(fd, "N", sizeof("N"), 0);
                    break;
                }
                else
                {
                    puts("错误选择!");
                    goto Again;
                }

                char buff[512];
                recv(fd, buff, sizeof(buff), 0);
                File_Data temp;
                strcpy(temp.Path, buff);
                istrans = true;
                Recv_Data((void *)&fd, (void *)&temp);
            }
        }
        else {
            close(fd);
            break;
        }
    }
}

void *Self_IP(void *IO)
{
    IP_STRUCT *n = (struct IP_STRUCT *)IO;
    FILE *P = popen("ifconfig -a|grep inet|grep -v 127.0.0.1|grep -v inet6|awk '{print $2}'|tr -d 'addr:'","r");

    char IP[1024];
    fread(IP, sizeof(char), sizeof(IP), P);
    std::string str;
    str = IP;
    if (str[str.size() - 1] == '\n')
        str.resize((str.size() - 1));
    sprintf(n->IP, "%s", str.c_str());
    char *Line = new char[256], *ptr;
    strcpy(Line, str.c_str());
    ptr = strtok(Line, ".");
    int count = 0;
    n->ip[count] = atoi(ptr);
    while (ptr)
    {
        ptr = strtok(NULL, ".");
        if (ptr)
        {
            count += 1;
            n->ip[count] = atoi(ptr);
        }

    }

    char temp1[32];

    char ip3[12];
    sprintf(ip3, "%d", n->ip[3]);
    std::string str1 = ip3;

    if (str1.size() > 2)
        sprintf(temp1, "22%d", n->ip[3]);
    else if (str1.size() <= 2)
        sprintf(temp1, "222%d", n->ip[3]);

    n->PORT = atoi(temp1);
    pclose(P);
    free(Line);
}

void *Server(void *p)
{
    IP_STRUCT n = *(struct IP_STRUCT *)p;
    n.Ser_fd = socket(AF_INET, SOCK_STREAM, 0);

    struct sockaddr_in Saddr;
    Saddr.sin_family = AF_INET;
    Saddr.sin_port = htons(n.PORT);
    Saddr.sin_addr.s_addr = htons(INADDR_ANY);

    if (bind(n.Ser_fd, (struct sockaddr *)&Saddr, sizeof(Saddr)) == -1)
        perror("绑定失败");


    if (listen(n.Ser_fd, 15) == -1)
        perror("监听失败");


    while (true)
    {
        struct sockaddr_in fromaddr;
        socklen_t len = sizeof(fromaddr);
        n.Cli_fd = accept(n.Ser_fd, (struct sockaddr *)&fromaddr, &len);

        pthread_t user;
        pthread_create(&user, 0, User_thread, &n.Cli_fd);
        //pthread_join(user, NULL);
    }

}

void *Client(void *ii)
{

    IP_STRUCT *ai = (struct IP_STRUCT *)ii;


    ai->Cli_fd = socket(AF_INET, SOCK_STREAM, 0);

        struct sockaddr_in Cliaddr;

        Cliaddr.sin_family = AF_INET;

        Cliaddr.sin_port = htons(0);

    Cliaddr.sin_addr.s_addr = htons(INADDR_ANY);


    if (bind(ai->Cli_fd,(zhang *)&Cliaddr,sizeof(Cliaddr)))
       perror("绑定失败");
       
       
    struct sockaddr_in Seraddr;
    
    Seraddr.sin_family = AF_INET;
    
    Seraddr.sin_port = htons(ai->PORT);
    
    Seraddr.sin_addr.s_addr = inet_addr(ai->IP);


    if (connect(ai->Cli_fd, (zhang *) &Seraddr, sizeof(Seraddr)) < 0)
    {
        // perror("连接失败");
        ai->connected = false;
    }
    else
        ai->connected = true;

}

void *ping(void *ii)
{
    fd_set rset;
    fd_set wset;

    IP_STRUCT *ai = (struct IP_STRUCT *)ii;

    int sockfd = socket(AF_INET, SOCK_STREAM, 0);

        struct sockaddr_in addr;

        addr.sin_family = AF_INET;

        addr.sin_port = htons(ai->PORT);
    
    addr.sin_addr.s_addr = inet_addr(ai->IP);

    int flag = fcntl(sockfd, F_GETFL, 0);
    fcntl(sockfd, F_SETFL, flag | O_NONBLOCK);
    struct timeval tm;
    tm.tv_sec = TIMEOUT;
    tm.tv_usec = 0;

    if (connect(sockfd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
    {
        FD_ZERO(&rset);
        FD_ZERO(&wset);
        FD_SET(sockfd, &rset);
        FD_SET(sockfd, &wset);
        int error;
        socklen_t len = sizeof(error);
        if (select(sockfd + 1, &rset, &wset, NULL, &tm) > 0)
        {
            getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len);
            if (error == 0)
                ai->is_ip = true;
            else
                ai->is_ip = false;
        }

    }
    else
        ai->is_ip = true;

    close(sockfd);
}

IP_STRUCT Self;
IP_STRUCT native[15];
int uid = 0;
void *Up_Load(void *p);
void *Init(void *p);
void *ChangeN(void *p);

void *Up_Load(void *p)
{
    if (uid == 0)
        puts("没有可配对用户");
    else
    {
        int total = 0;
        for (int i = 1; i <= uid; i++)
        {
            Client((void*)&native[i]);
            if (native[i].connected == true) {
            printf("用户名:%s, IP地址:%s, ID:%d\n", native[i].User_Name, native[i].IP,
                   native[i].id);
            total += 1;
            }
            else
            close(native[i].Cli_fd);
        }
        
        if (total > 0) {

        printf("请输入需要配对用户的ID\n输入: ");

        int choose;
        std::cin >> choose;
      Again:
        printf("请输入需要发送的文件绝对路径\n输入: ");
        char choise[512];
        std::cin >> choise;
        if (access(choise, 0) == -1)
        {
            puts("路径错误,请重新输入!");
            goto Again;
        }
        MSG_STRUCT Msg;
        Msg.File_Len = (GetFileSize(choise)) / 1024.0f / 1024.0f;
        sprintf(Msg.msg, "FILE_TRANS");
        sprintf(Msg.User_Name, "%s", User_Name);
        send(native[choose].Cli_fd, (void *)&Msg, sizeof(Msg), 0);
        bzero(native[choose].buf, sizeof(native[choose].buf));
        recv(native[choose].Cli_fd, native[choose].buf, sizeof(native[choose].buf), 0);
        if (strcmp(native[choose].buf, "N") == 0)
        {
            std::cout << native[choose].User_Name << "拒绝接收你的文件!" << std::endl;
            close(native[choose].Cli_fd);
        }
        else
        {
            send(native[choose].Cli_fd, choise, sizeof(choise), 0);
            File_Data tempf;
            tempf.size = (GetFileSize(choise)) / 1024.0f / 1024.0f;
            strcpy(tempf.Path, choise);
            Send_Data((void *)&native[choose].Cli_fd, (void *)&tempf);
        }
        
      }
      else {
        puts("没有可配对用户");
        uid = 0;
      }

    }

}

void *Init(void *p)
{
    uid = 0;
    memset(native, 0, sizeof(native));

    for (int aa = ipv4; aa < ipv4 + 13; aa++)
    {
        IP_STRUCT ip = *(struct IP_STRUCT *)p;

        if (aa == ip.ip[3])
            continue;

        char buf[64];

        sprintf(ip.IP, "%d.%d.%d.%d", ip.ip[0], ip.ip[1], ip.ip[2], aa);
        
        char ip3[12],temp1[12];
        sprintf(ip3, "%d", aa);
        std::string str1 = ip3;

        if (str1.size() > 2)
        sprintf(temp1, "22%d", aa);
        else if (str1.size() <= 2)
        sprintf(temp1, "222%d", aa);

        ip.PORT = atoi(temp1);

        ping((void *)&ip);

        if (ip.is_ip == true)
        {
            bzero(ip.buf, sizeof(ip.buf));
            Client((void *)&ip);
            if (ip.connected == true)
            {
                send(ip.Cli_fd, "INIT_OK", strlen("INIT_OK"), 0);
                recv(ip.Cli_fd, ip.User_Name, sizeof(ip.User_Name), 0);
                uid += 1;
                ip.id = uid;
                native[uid] = ip;
            }
        }

    }

    if (uid != 0)
        printf("局域网内共嗅探到%d名用户\n", uid);
    else
        printf("局域网内未曾嗅探到一名用户\n");


    // pthread_exit(0);
}


void *Menu(void *p)
{

    while (true)
    {
        while (istrans == true);
        puts("------------------------");

        puts("Zhang-局域网文件传输终端程序");

        puts("(1) 局域网嗅探");

        puts("(2) 传输文件");

        puts("(3) 更改用户名");

        puts("------------------------");

        std::cout << "请输入你需要使用功能的序号: " << std::endl;

        char choise[12];

        std::cin >> choise;

        if (atoi(choise) == 1)
           Init((void *)&Self);
        else if (atoi(choise) == 2)
           Up_Load(NULL);
        else if (atoi(choise) == 3)
           ChangeN(NULL);
        else if (strcmp(choise,"Y") == 0)
           YN = 'Y';
        else if (strcmp(choise,"N") == 0)
           YN = 'N';
        else  puts("选择错误");
        
        sleep(1);

        std::cout << std::endl << std::endl;
    }
}

void *ChangeN(void *p)
{
    FILE *Name = fopen(CONFIG, "w+");
    std::cout << "请输入用户名: ";
    std::cin >> User_Name;
    fprintf(Name, "%s", User_Name);
    fclose(Name);
}

int main()
{
    if (access("/sdcard/Server/", 0) == -1)
        system("mkdir /sdcard/Server/");

    if (access(CONFIG, 0) == -1)
    {
        ChangeN(NULL);
    }
    else
    {
        FILE *Name = fopen(CONFIG, "r+");
        fscanf(Name, "%s", User_Name);
        fclose(Name);
    }

    Self_IP((void *)&Self);

    char ip3[12];
    sprintf(ip3, "%d", Self.ip[3]);
    std::string str = ip3;

    if (str.size() > 1)
    {
        str.resize(str.size() - 1);
        str += "0";
    }
    else if (str.size() == 1)
        str = "0";

    ipv4 = atoi(str.c_str());

    pthread_t Ser;

    pthread_create(&Ser, NULL, Server, &Self);

    pthread_t menu;

    pthread_create(&menu, NULL, Menu, NULL);

    for (;;);
}

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux虚拟机中文件,可以使用C语言中的socket编程实现。以下是一个简单的例子: 1. 在发送端(虚拟机上): ``` #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/socket.h> #include <arpa/inet.h> #include <sys/stat.h> #include <fcntl.h> #define PORT 8080 int main(int argc, char const *argv[]) { int sock = 0; struct sockaddr_in serv_addr; char *file_path = "/path/to/file"; // 创建socket if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { printf("\n Socket creation error \n"); return -1; } // 设置服务器地址 serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(PORT); if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0) { printf("\nInvalid address/ Address not supported \n"); return -1; } // 连接服务器 if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { printf("\nConnection Failed \n"); return -1; } // 打开文件并读取内容 int fd = open(file_path, O_RDONLY); if (fd < 0) { printf("\nFile open error\n"); return -1; } struct stat st; fstat(fd, &st); size_t file_size = st.st_size; char *file_buf = malloc(file_size); read(fd, file_buf, file_size); // 发送文件大小 write(sock, &file_size, sizeof(file_size)); // 发送文件内容 write(sock, file_buf, file_size); // 关闭文件socket close(fd); close(sock); return 0; } ``` 2. 在接收端(本地机器上): ``` #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/socket.h> #include <arpa/inet.h> #define PORT 8080 int main(int argc, char const *argv[]) { int server_fd, new_socket; struct sockaddr_in address; int addrlen = sizeof(address); char buffer[1024] = {0}; // 创建socket if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) { perror("socket failed"); exit(EXIT_FAILURE); } // 绑定端口并监听 address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; address.sin_port = htons(PORT); if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) { perror("bind failed"); exit(EXIT_FAILURE); } if (listen(server_fd, 3) < 0) { perror("listen"); exit(EXIT_FAILURE); } // 接收连接 if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t *)&addrlen)) < 0) { perror("accept"); exit(EXIT_FAILURE); } // 接收文件大小 size_t file_size; read(new_socket, &file_size, sizeof(file_size)); printf("File size: %zu\n", file_size); // 接收文件内容 char *file_buf = malloc(file_size); read(new_socket, file_buf, file_size); // 将文件写入本地 FILE *fp = fopen("/path/to/destination", "wb"); fwrite(file_buf, 1, file_size, fp); fclose(fp); // 关闭socket close(new_socket); close(server_fd); return 0; } ``` 在这个例子中,我们首先打开要输的文件并读取其内容,然后使用socket连接将文件大小和内容发送到另一端。在接收端,我们先接收文件大小,然后根据大小接收文件内容,并将其写入本地磁盘。请注意,这个例子中使用的是本地回环地址127.0.0.1和端口号8080,您需要根据您的实际情况进行更改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值