c - 通过c中的套接字发送多条消息

标签 c sockets network-programming

所以在这个程序中,我尝试分两步将文件内容和文件名从客户端发送到服务器。我尝试使用 memset() 清空缓冲区,以便将其用于存储文件名,但是后来我意识到文件名与内容一起被传递到缓冲区中,所以没有意义memset() 的。因此,我需要将两个传输分开我正在考虑为第一个进程关闭缓冲区然后再次为第二个传输打开它,我不确定如何继续。

这是我的代码:

Server.c

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

int main(int argc, char *argv[]){

    int fd =0, confd = 0;
    struct sockaddr_in serv_addr;

   char buff[1025];
   int num;

   fd = socket(AF_INET, SOCK_STREAM, 0);
   printf("Socket created\n");

   memset(&serv_addr, '0', sizeof(serv_addr));
   memset(buff, '0', sizeof(buff));

   serv_addr.sin_family = AF_INET;
   serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
   serv_addr.sin_port = htons(5000);

   bind(fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));

   listen(fd, 10);

   while(1){

       confd = accept(fd, (struct sockaddr*)NULL, NULL);

       FILE* fp = fopen( "create.txt", "wb");

       int b = recv(confd, buff, 1024, 0);

       if(fp!=NULL){

           while(b>0){

           fwrite(buff, 1, b, fp);
           b = recv(confd, buff, 1024, 0);
           }
       }

       else{
           printf("Error!");
       }

       printf("Got it :)\n");
       //printf("Buff before: %s\n", buff);

       memset(buff, 0, sizeof(buff));

       num = read(confd, buff, 1024);
       //printf("Buff after: %s\n", buff);

       if(num<0){
           printf("error reading the socket");}
       else{
           printf("File uploaded: %s\n", buff);
       }

       //close(confd);
       fclose(fp);
 }
 return 0;
 }

客户端.c

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


int main(int argc, char *argv[]){

    int i=0, k=0,num;
    char ip[50];
    char upfile[50];
    char dwfile[50];



    for(i=0; i<argc; i++){
        if(strcmp(argv[i], "-i")==0){
            strcpy(ip, argv[i+1]);
        }

        else if(strcmp(argv[i],"-u")==0){
            strcpy(upfile, argv[i+1]);
            k =2;
        }

        else if(strcmp(argv[i], "-d")==0){
            strcpy( dwfile, argv[i+1]);
            k=3;    }

       /*  else(argv[i] = "-l"){
       }*/

    }
    printf("%s %s %s", ip, upfile, dwfile);

    int sfd =0, n=0, c;
    char rbuff[1024];

    struct sockaddr_in serv_addr;

    memset(rbuff, '0', sizeof(rbuff));
    sfd = socket(AF_INET, SOCK_STREAM, 0);

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(5000);
    serv_addr.sin_addr.s_addr = inet_addr(ip);

    c = connect(sfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
    if(c==-1){
        perror("Connect");
        return 1;
    }

   if (k==2){
       printf("==========This is the upload function");
       FILE *fp = fopen(upfile, "rb");

       if(fp == NULL){
           fprintf(stderr, "oh no!");
           return 1;
       }

       char sendbuffer[100];

       int b = fread(sendbuffer, 1, sizeof(sendbuffer),fp);
       while(b>0){
           send(sfd, sendbuffer, b, 0);
           b = fread(sendbuffer, 1, sizeof(sendbuffer),fp);
       }

       num = write(sfd, upfile, strlen(upfile));
       fclose(fp);

       printf("Send filename: %s", upfile);
       printf("============End upload!");
   }

   return 0;

}

有人能帮忙吗?

编辑 1:

在发送文件内容之前发送文件名似乎可行,但是这样做会打印一长串零。例如:上传的文件:tt.txt000000000000000000000....

最佳答案

有两种常见的解决方案:一种是使用分隔符,一种特殊的字节或字节序列,它不能出现在消息数据中,并标记两条消息之间的分隔符。在您发送二进制文件的情况下,这并不可行,因为实际上没有安全序列。

另一种常用方法是使用一个特殊的固定大小的 header ,其中包含您发送的数据的长度。然后您只需先发送这个固定大小的 header ,然后再发送实际数据。


在您的情况下,您实际上可以使用这两种方法,但我真的建议您发送文件名,否则服务器将很难打开文件并写入数据。

您可以发送带有终止零的文件名,从而将字符串终止符作为文件名和文件数据之间的字段分隔符。

或者您可以同时发送文件名的长度文件数据,后跟名称和数据。

关于c - 通过c中的套接字发送多条消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30452855/

相关文章:

c - 标准输出重定向

c - 在三元运算中设置 2 个值 - C

c - 避免需要初始化数组的技巧

Java套接字编程头

c - 异步 C UDP 客户端

c - 与远程主机安全连接并检查

c++:流式传输和速率调节

Java - url.openConnection() 和 httpsUrlConnection.connect() 首次调用时运行缓慢

c - 如何将 udp 套接字绑定(bind)到单个单播地址

java - 客户端如何知道连接到哪个套接字?