基于Socket写一个ssh通讯,并且完美解决粘包问题

注意:本例所有代码均在windows平台下实现,如果是Linux或者Mac os下可能会存在诧异并产生一定问题。
因此:如果需要测试请在windows平台下进行。
首先来看客户端实现代码:

import socket

client = socket.socket()
client.connect(('localhost',9999))

while True:
    msg = input('>>:').strip()
    if len(msg) == 0: continue
    client.send(msg.encode('utf-8'))
    data_rev_size = client.recv(1024) #接收命令的大小
    print(data_rev_size)
    client.send('已经准备好接收数据了。'.encode('utf-8'))
    re_size = 0
    re_data = b''
    while re_size != int(data_rev_size.decode()):
        data_rev = client.recv(1024)
        re_size += len(data_rev)
        print(re_size)
        re_data += data_rev
    print(re_data.decode())

client.close()

然后再来看服务端代码:

import socket
import os

import time

server = socket.socket()
server.bind(('localhost',9999))
server.listen(5)

while True:
    con,addr = server.accept()
    while True:
        try:
            data = con.recv(10240)  # 接收数据
            cmd_res = os.popen(data.decode()).read()
            # print(cmd_res)
            if len(cmd_res) == 0:
                cmd_res = 'This commit is not recve'
            con.send(str(len(cmd_res.encode('utf-8'))).encode('utf-8')) #先大大小给客户端
            # time.sleep(0.5)  #这个是为了避免数据粘包的情况,直接等待0.5s
            # 使得它超时,然后直接执行下一条命令
            # 但正常不能这样
            sure = con.recv(1024) #最新的解决粘包的问题
            print(sure.decode())
            con.send(str(cmd_res).encode('utf-8')) #再把命令返回给客户端
        except ConnectionResetError as e:
            print('客户端已经断开!')
            break
    con.close()

server.close()

这里测试的话,请先运行服务端代码,然后运行客户端代码,
然后输入windows命令进行测试,如dir、ipconfig、pwd等

下面是一个简单的 C# Socket 通讯解决粘包的示例: ```csharp using System; using System.Net; using System.Net.Sockets; using System.Text; public class SocketServer { private Socket listener; private const int BUFFER_SIZE = 1024; private byte[] buffer = new byte[BUFFER_SIZE]; public void Start() { listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); listener.Bind(new IPEndPoint(IPAddress.Any, 8080)); listener.Listen(10); Console.WriteLine("Server started on port 8080."); while (true) { Socket client = listener.Accept(); Console.WriteLine("Client connected: " + client.RemoteEndPoint.ToString()); // Start receiving data from client client.BeginReceive(buffer, 0, BUFFER_SIZE, 0, new AsyncCallback(OnReceive), client); } } private void OnReceive(IAsyncResult ar) { Socket client = (Socket)ar.AsyncState; int bytesRead = client.EndReceive(ar); if (bytesRead > 0) { // Convert received bytes to string string receivedData = Encoding.UTF8.GetString(buffer, 0, bytesRead); // Process received data Console.WriteLine("Received data: " + receivedData); // Continue receiving data from client client.BeginReceive(buffer, 0, BUFFER_SIZE, 0, new AsyncCallback(OnReceive), client); } else { // Client has disconnected Console.WriteLine("Client disconnected: " + client.RemoteEndPoint.ToString()); client.Close(); } } } public class SocketClient { private Socket client; private const int BUFFER_SIZE = 1024; private byte[] buffer = new byte[BUFFER_SIZE]; public void Connect() { client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); client.BeginConnect(new IPEndPoint(IPAddress.Loopback, 8080), new AsyncCallback(OnConnect), null); } private void OnConnect(IAsyncResult ar) { Console.WriteLine("Connected to server."); client.EndConnect(ar); // Start receiving data from server client.BeginReceive(buffer, 0, BUFFER_SIZE, 0, new AsyncCallback(OnReceive), client); } private void OnReceive(IAsyncResult ar) { Socket client = (Socket)ar.AsyncState; int bytesRead = client.EndReceive(ar); if (bytesRead > 0) { // Convert received bytes to string string receivedData = Encoding.UTF8.GetString(buffer, 0, bytesRead); // Process received data Console.WriteLine("Received data: " + receivedData); // Continue receiving data from server client.BeginReceive(buffer, 0, BUFFER_SIZE, 0, new AsyncCallback(OnReceive), client); } else { // Server has disconnected Console.WriteLine("Server disconnected."); client.Close(); } } public void Send(string data) { byte[] sendData = Encoding.UTF8.GetBytes(data); client.BeginSend(sendData, 0, sendData.Length, 0, new AsyncCallback(OnSend), null); } private void OnSend(IAsyncResult ar) { client.EndSend(ar); } } class Program { static void Main(string[] args) { // Start server SocketServer server = new SocketServer(); server.Start(); // Connect client to server SocketClient client = new SocketClient(); client.Connect(); // Send data to server client.Send("Hello, server!"); Console.ReadLine(); } } ``` 这个示例中,我们使用了异步的 BeginReceive 和 BeginSend 方法来在接收和发送数据时不阻塞主线程。在接收数据时,我们先接收到一部分数据,然后判断是否收到了完整的数据,如果没有就继续接收。在发送数据时,我们将要发送的数据转换成字节数组后,使用 BeginSend 方法发送,然后在回调函数中调用 EndSend 方法结束发送。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

haeasringnar

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值