qq_34486642
qq_34486642
采纳率100%
2020-03-03 22:28

linux下socket数据传输错误

120
已采纳

我想在linux下用openssl做一个socket传输的加密demo,但是原来没接触过,有些问题。下面这个是我发送和接收的代码,里面发送和接收了rsa公钥的数据和长度,但是不是每次发送都能成功,比如第一次成功接收,之后再次运行这两个程序,就接收不到了,求帮助解决。

//send.cpp
int sendKey(unsigned char *pk,int pk_len,int serv_sock){
    int32_t conv=htonl(pk_len);
    char *data = (char*)&conv;
    int len = sizeof(conv);
    char *key=(char*)pk;
    struct sockaddr_in clnt_addr;
    socklen_t clnt_addr_size = sizeof(clnt_addr);
    int clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_size);
    int rc1=write(clnt_sock, data, len);
    if(rc1<0){
        printf("errno is %d\n",errno);
    }
    int rc2=write(clnt_sock, key, pk_len);
    if(rc2<0){
        printf("errno is %d\n",errno);
    }    
    close(clnt_sock);
}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
int main(){
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    struct sockaddr_in serv_addr;
    memset(&serv_addr, 0, sizeof(serv_addr));  
    serv_addr.sin_family = AF_INET;  
    serv_addr.sin_addr.s_addr = inet_addr("192.168.0.100");  
    serv_addr.sin_port = htons(8000);  
    connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));

    unsigned char buffer[100000];
    int32_t pk_len=0;
    char *data=(char*)&pk_len;
    read(sock, data, sizeof(pk_len));
    read(sock, buffer, ntohl(pk_len));
    for (int i=0; i<ntohl(pk_len); i++)
    {
        printf("0x%02x, ", *(buffer+i));
    }
    printf("pklen from server:%d\n",ntohl(pk_len));


    close(sock);
    return 0;
}

图片说明

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答

2条回答

  • dashicaineng 蔡能教授,网站特聘专家 1年前

    因为你握手的时候调用了 close(clnt_sock); ,之后客户端发送,还需要重新调用 accept 才行。

    看下下面的例子:

    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <netdb.h>
    #include <stdio.h>
    #include <errno.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    /************************************************************************************************************************
    1、int socket(int family,int type,int protocol)
    family:
        指定使用的协议簇:AF_INET(IPv4) AF_INET6(IPv6) AF_LOCAL(UNIX协议) AF_ROUTE(路由套接字) AF_KEY(秘钥套接字)
    type:
        指定使用的套接字的类型:SOCK_STREAM(字节流套接字) SOCK_DGRAM
    protocol:
        如果套接字类型不是原始套接字,那么这个参数就为0
    2、int bind(int sockfd, struct sockaddr *myaddr, int addrlen)
    sockfd:
        socket函数返回的套接字描述符
    myaddr:
        是指向本地IP地址的结构体指针
    myaddrlen:
        结构长度
    struct sockaddr{
        unsigned short sa_family; //通信协议类型族AF_xx
        char sa_data[14];  //14字节协议地址,包含该socket的IP地址和端口号
    };
    struct sockaddr_in{
        short int sin_family; //通信协议类型族
        unsigned short int sin_port; //端口号
        struct in_addr sin_addr; //IP地址
        unsigned char si_zero[8];  //填充0以保持与sockaddr结构的长度相同
    };
    3、int connect(int sockfd,const struct sockaddr *serv_addr,socklen_t addrlen)
    sockfd:
        socket函数返回套接字描述符
    serv_addr:
        服务器IP地址结构指针
    addrlen:
        结构体指针的长度
    4、int listen(int sockfd, int backlog)
    sockfd:
        socket函数绑定bind后套接字描述符
    backlog:
        设置可连接客户端的最大连接个数,当有多个客户端向服务器请求时,收到此值的影响。默认值20
    5、int accept(int sockfd,struct sockaddr *cliaddr,socklen_t *addrlen)
    sockfd:
        socket函数经过listen后套接字描述符
    cliaddr:
        客户端套接字接口地址结构
    addrlen:
        客户端地址结构长度
    6、int send(int sockfd, const void *msg,int len,int flags)
    7、int recv(int sockfd, void *buf,int len,unsigned int flags)
    sockfd:
        socket函数的套接字描述符
    msg:
        发送数据的指针
    buf:
        存放接收数据的缓冲区
    len:
        数据的长度,把flags设置为0
    *************************************************************************************************************************/
    int main(int argc, char *argv[])
    {
        int fd, new_fd, struct_len, numbytes,i;
        struct sockaddr_in server_addr;
        struct sockaddr_in client_addr;
        char buff[BUFSIZ];
    
        server_addr.sin_family = AF_INET;
        server_addr.sin_port = htons(8000);
        server_addr.sin_addr.s_addr = INADDR_ANY;
        bzero(&(server_addr.sin_zero), 8);
        struct_len = sizeof(struct sockaddr_in);
    
        fd = socket(AF_INET, SOCK_STREAM, 0);
        while(bind(fd, (struct sockaddr *)&server_addr, struct_len) == -1);
        printf("Bind Success!\n");
        while(listen(fd, 10) == -1);
        printf("Listening....\n");
        printf("Ready for Accept,Waitting...\n");
        new_fd = accept(fd, (struct sockaddr *)&client_addr, &struct_len);
        printf("Get the Client.\n");
        numbytes = send(new_fd,"Welcome to my server\n",21,0); 
        while((numbytes = recv(new_fd, buff, BUFSIZ, 0)) > 0)
        {
            buff[numbytes] = '\0';
            printf("%s\n",buff);
                if(send(new_fd,buff,numbytes,0)<0)  
                {  
                    perror("write");  
                    return 1;  
                }  
        }
        close(new_fd);
        close(fd);
        return 0;
    }
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <string.h>
    #include <netdb.h>
    #include <sys/types.h>
    #include <netinet/in.h>
    #include <sys/socket.h>
    #include <arpa/inet.h>
    
    int main(int argc,char *argv[])
    {
        int sockfd,numbytes;
        char buf[BUFSIZ];
        struct sockaddr_in their_addr;
        printf("break!");
        while((sockfd = socket(AF_INET,SOCK_STREAM,0)) == -1);
        printf("We get the sockfd~\n");
        their_addr.sin_family = AF_INET;
        their_addr.sin_port = htons(8000);
        their_addr.sin_addr.s_addr=inet_addr("127.0.0.1");
        bzero(&(their_addr.sin_zero), 8);
    
        while(connect(sockfd,(struct sockaddr*)&their_addr,sizeof(struct sockaddr)) == -1);
        printf("Get the Server~Cheers!\n");
        numbytes = recv(sockfd, buf, BUFSIZ,0);//接收服务器端信息  
        buf[numbytes]='\0';  
        printf("%s",buf);
        while(1)
        {
            printf("Entersome thing:");
            scanf("%s",buf);
            numbytes = send(sockfd, buf, strlen(buf), 0);
                numbytes=recv(sockfd,buf,BUFSIZ,0);  
            buf[numbytes]='\0'; 
            printf("received:%s\n",buf);  
        }
        close(sockfd);
        return 0;
    }
    

    问题解决请点个采纳

    点赞 5 评论 复制链接分享
  • phenix2009 白色一大坨 1年前

    你这个实现的是tcp服务器向客户端发送数据,你服务器里面,accept应该是在检测到有连接请求时候才做,而不是每次发送都做一次,且发送后直接关闭socket,这不合理;
    正常设计应该是你服务器接收到客户端连接,获取socket句柄,之后在需要时候用句柄发送,退出程序时候才进行关闭;
    客户端方面,你接收字符串部分应该没有做等待,请加一个等待,或者循环接收数据,根据接收是否成功进行分别处理。

    点赞 2 评论 复制链接分享