Управление сокетами в c и python: почему я получаю двойные отпечатки? - PullRequest
0 голосов
/ 12 июня 2019

У меня есть сервер сокетов в Python, который будет устанавливать ssh-соединение с x-клиентами на языке C;клиент получает команды для отправки на сервер python, которые делают это через Paramiko, затем сервер отправляет результат обратно клиенту C и так далее.Проблема в том, что я получаю 2 или более реплицированных ответа (иногда и команды) из этого приложения.

И коды Python, и C получают вход / выход асинхронно, что означает, что: вход или выход вделается основной, а другая часть находится в потоке.

Код клиента C:

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

void *receive_message(void *sock_desc)
{
    int receive;
    char message[2000] = {0};
    while (1){
        memset(message,0,sizeof(message));
        receive = recv(*((int *) sock_desc),message,2000,0);
        if (receive>0){
            printf("%s\n", message);
        }else{
            printf("message error:%d\n",receive);
        }

    }
    return NULL;

}


static int socketConnection(){
    int PORT = 8081;
    struct sockaddr_in address;
    int sock = 0, valread;
    struct sockaddr_in serv_addr;
    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {

        printf("\n Socket creation error \n");
        return -1;
    }

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

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(PORT);

    // Convert IPv4 and IPv6 addresses from text to binary form
    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;
    }
    char message[2000] = {0};
    for (int i=0;i<5;i++){
        strcat(message,my_argv[i]);
        strcat(message,",");
        }
    int *new_sock;
    new_sock = malloc(sizeof(int));
    *new_sock = sock;
    send(sock , message ,sizeof(message) , 0 );
    pthread_t receive_thread;
    printf("Before Thread\n");
    pthread_create(&receive_thread, NULL, receive_message, (void * ) &sock);
    printf("After Thread\n");
    char command[2000] ={0};
    while (1){
        fgets(command,sizeof(command),stdin);
        send(sock , command ,sizeof(command) , 0 );
        memset(command,0,sizeof(command));
    }
    return 1;
}

int main(int argc, char const *argv[])
{
    return socketConnection();;
}

server.py:

import paramiko_ssh
import socket
from threading import Thread
import time
import paramiko





class Connection:
    def __init__(self, address, username, password, sock):
        self.address=address
        self.username=username
        self.password=password
        self.sock=sock



    def command_loop(self):
        self.client = paramiko.SSHClient()
        self.client.set_missing_host_key_policy(paramiko.client.AutoAddPolicy())
        self.client.connect(self.address, username=self.username, password=self.password)
        self.transport = paramiko.Transport(self.address, 22)
        self.transport.connect(username=self.username, password=self.password)

        self.shell = self.client.invoke_shell()

        cont = 0
        data = ""
        while True:
            self.wait_answer_loop()
            command = self.sock.recv(2000)
            self.shell.send(command + "\n")


    def wait_answer_loop(self):
        data = ""
        received_answer = False
        while not received_answer:
            if self.shell.recv_ready():
                data = self.shell.recv(4096)
                strdata = str(data)
                strdata.replace('\r', '')
                self.sock.send(strdata.split('$')[0]+'$')
                received_answer = True
            else:
                time.sleep(1)
        print('Finished loop')



def clientthread(conn):
    #sends a message to the client whose user object is conn
    message = conn.recv(2000)
    if message:
        print("message:" + message)
        my_argv = message.split(",")
        del(my_argv[len(my_argv)-1])
    connection= paramiko_ssh.ssh("some.ip.address.to.ssh","user","password",conn)
    connection.openShell()
    while True:
       command = conn.recv(4096)
       #print("command received"+str(command))
       if command.startswith(" "):
           command = command[1:]
       connection.sendShell(command)









server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
IP_address = "localhost"
Port = 8081
server.bind((IP_address, Port))
server.listen(1000)
clients = {}
cont=0
print("waiting for new connections")
while True:
    client, client_address = server.accept()
    print("%s:%s has connected." % client_address)
    Thread(target=clientthread, args=(client,)).start()



#conn.close()
#server.close()

paramiko_ssh.py

import threading, paramiko,socket

class ssh:
    shell = None
    client = None
    transport = None

    def __init__(self, address, username, password,socket):
        print("Connecting to server on ip", str(address) + ".")
        self.client = paramiko.client.SSHClient()
        self.client.set_missing_host_key_policy(paramiko.client.AutoAddPolicy())
        self.socket=socket
        self.client.connect(address, username=username, password=password, look_for_keys=False)
        self.transport = paramiko.Transport((address, 22))
        self.transport.connect(username=username, password=password)
        thread = threading.Thread(target=self.process)
        thread.daemon = True
        thread.start()

    def closeConnection(self):
        if(self.client != None):
            self.client.close()
            self.transport.close()

    def openShell(self):
        self.shell = self.client.invoke_shell()

    def sendShell(self, command):
        if(self.shell):
            self.shell.send(command + "\n")
        else:
            print("Shell not opened.")



    def process(self):
        global connection
        strdata=''

        while True:
            # Print data when available
            if self.shell != None and self.shell.recv_ready():
                alldata = self.shell.recv(4096)
                while self.shell.recv_ready():
                    alldata += self.shell.recv(4096)
                strdata = str(alldata)
                strdata.replace('\r', '')
                print(strdata +"")
                self.socket.send(strdata +"")


Я предполагаю, что ясделал что-то не так в управлении сокетами при входе / выходе, но я не вижу, в чем проблема.

...