You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Client-Server-Client模型下,如何随数据向接收端传递发送端IP

解决方案:在C/S/C模型中传递发送端IP信息

方案一:服务器直接获取发送端IP(推荐,更可靠)

服务器可直接从与发送端建立的Socket连接中提取真实IP,无需客户端额外传递,能避免客户端伪造IP的问题。

服务器端代码修改

try
{
    // 获取发送端真实IP地址
    string senderIp = ((IPEndPoint)current.RemoteEndPoint).Address.ToString();
    
    // 先接收数据长度(解决粘包问题)
    byte[] lengthBuffer = new byte[4];
    current.Receive(lengthBuffer, 4, SocketFlags.None);
    int dataLength = BitConverter.ToInt32(lengthBuffer, 0);
    
    // 循环接收完整数据,避免网络截断
    byte[] dataBuffer = new byte[dataLength];
    int receivedBytes = 0;
    while (receivedBytes < dataLength)
    {
        receivedBytes += current.Receive(dataBuffer, receivedBytes, dataLength - receivedBytes, SocketFlags.None);
    }
    
    // 构建含IP的转发数据包:IP长度(4字节) + IP字节数组 + 数据长度(4字节) + 原始数据
    byte[] ipBytes = Encoding.UTF8.GetBytes(senderIp);
    byte[] forwardBuffer = new byte[4 + ipBytes.Length + 4 + dataBuffer.Length];
    Buffer.BlockCopy(BitConverter.GetBytes(ipBytes.Length), 0, forwardBuffer, 0, 4);
    Buffer.BlockCopy(ipBytes, 0, forwardBuffer, 4, ipBytes.Length);
    Buffer.BlockCopy(BitConverter.GetBytes(dataLength), 0, forwardBuffer, 4 + ipBytes.Length, 4);
    Buffer.BlockCopy(dataBuffer, 0, forwardBuffer, 4 + ipBytes.Length + 4, dataLength);
    
    // 替换为你的接收端Socket,完成转发
    // receiverSocket.Send(forwardBuffer, forwardBuffer.Length, SocketFlags.None);
    
    // 测试用:按IP命名保存图片
    ImageConverter convertData = new ImageConverter();
    Image image = (Image)convertData.ConvertFrom(dataBuffer);
    image.Save($"{senderIp}_image.png");
    Console.WriteLine($"来自 {senderIp} 的图片已保存");
}
catch (Exception ex)
{
    Console.WriteLine("处理数据失败");
    logFileWrite("处理数据失败");
    Console.WriteLine(ex.ToString());
}

客户端代码修改(补充粘包处理)

try
{
    // 捕获屏幕并转为字节数组
    Bitmap bm = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
    Graphics g = Graphics.FromImage(bm);
    g.CopyFromScreen(0, 0, 0, 0, bm.Size);
    MemoryStream ms = new MemoryStream();
    bm.Save(ms, ImageFormat.Jpeg);
    byte[] dataBuffer = ms.ToArray();
    
    // 先发送数据长度,再发送实际数据
    byte[] lengthBytes = BitConverter.GetBytes(dataBuffer.Length);
    ClientLiveScreenSocket.Send(lengthBytes, 0, 4, SocketFlags.None);
    ClientLiveScreenSocket.Send(dataBuffer, 0, dataBuffer.Length, SocketFlags.None);
    
    Console.WriteLine($"发送成功,大小:{dataBuffer.Length / 1024} KB");
    logFileWrite($"发送成功,大小:{dataBuffer.Length / 1024} KB");
    Thread.Sleep(500);
}
catch (Exception ex)
{
    Console.WriteLine(ex.ToString());
}

接收端客户端解析逻辑

try
{
    // 解析IP信息
    byte[] ipLengthBuffer = new byte[4];
    clientSocket.Receive(ipLengthBuffer, 4, SocketFlags.None);
    int ipLength = BitConverter.ToInt32(ipLengthBuffer, 0);
    
    byte[] ipBytes = new byte[ipLength];
    clientSocket.Receive(ipBytes, ipLength, SocketFlags.None);
    string senderIp = Encoding.UTF8.GetString(ipBytes);
    
    // 解析数据内容
    byte[] dataLengthBuffer = new byte[4];
    clientSocket.Receive(dataLengthBuffer, 4, SocketFlags.None);
    int dataLength = BitConverter.ToInt32(dataLengthBuffer, 0);
    
    byte[] dataBuffer = new byte[dataLength];
    int receivedBytes = 0;
    while (receivedBytes < dataLength)
    {
        receivedBytes += clientSocket.Receive(dataBuffer, receivedBytes, dataLength - receivedBytes, SocketFlags.None);
    }
    
    // 处理数据(例:显示图片并标记来源IP)
    ImageConverter convertData = new ImageConverter();
    Image image = (Image)convertData.ConvertFrom(dataBuffer);
    Console.WriteLine($"收到来自 {senderIp} 的图片");
}
catch (Exception ex)
{
    Console.WriteLine(ex.ToString());
}

方案二:客户端主动传递IP(适用于自定义标识场景)

若需客户端传递自定义标识(而非真实IP),可让客户端在发送数据前主动携带IP信息。

客户端代码修改

try
{
    // 获取本地IP(可根据网卡选择对应IP)
    string localIp = Dns.GetHostEntry(Dns.GetHostName()).AddressList.FirstOrDefault(ip => ip.AddressFamily == AddressFamily.InterNetwork)?.ToString() ?? "127.0.0.1";
    byte[] ipBytes = Encoding.UTF8.GetBytes(localIp);
    
    // 捕获屏幕数据
    Bitmap bm = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
    Graphics g = Graphics.FromImage(bm);
    g.CopyFromScreen(0, 0, 0, 0, bm.Size);
    MemoryStream ms = new MemoryStream();
    bm.Save(ms, ImageFormat.Jpeg);
    byte[] dataBuffer = ms.ToArray();
    
    // 构建完整数据包:IP长度(4字节) + IP字节数组 + 数据长度(4字节) + 原始数据
    byte[] sendBuffer = new byte[4 + ipBytes.Length + 4 + dataBuffer.Length];
    Buffer.BlockCopy(BitConverter.GetBytes(ipBytes.Length), 0, sendBuffer, 0, 4);
    Buffer.BlockCopy(ipBytes, 0, sendBuffer, 4, ipBytes.Length);
    Buffer.BlockCopy(BitConverter.GetBytes(dataBuffer.Length), 0, sendBuffer, 4 + ipBytes.Length, 4);
    Buffer.BlockCopy(dataBuffer, 0, sendBuffer, 4 + ipBytes.Length + 4, dataBuffer.Length);
    
    // 发送数据包
    ClientLiveScreenSocket.Send(sendBuffer, sendBuffer.Length, SocketFlags.None);
    
    Console.WriteLine($"发送成功,来源IP:{localIp},大小:{dataBuffer.Length / 1024} KB");
    logFileWrite($"发送成功,来源IP:{localIp},大小:{dataBuffer.Length / 1024} KB");
    Thread.Sleep(500);
}
catch (Exception ex)
{
    Console.WriteLine(ex.ToString());
}

服务器端代码修改

try
{
    // 解析IP信息
    byte[] ipLengthBuffer = new byte[4];
    current.Receive(ipLengthBuffer, 4, SocketFlags.None);
    int ipLength = BitConverter.ToInt32(ipLengthBuffer, 0);
    
    byte[] ipBytes = new byte[ipLength];
    current.Receive(ipBytes, ipLength, SocketFlags.None);
    string senderIp = Encoding.UTF8.GetString(ipBytes);
    
    // 解析数据内容
    byte[] dataLengthBuffer = new byte[4];
    current.Receive(dataLengthBuffer, 4, SocketFlags.None);
    int dataLength = BitConverter.ToInt32(dataLengthBuffer, 0);
    
    byte[] dataBuffer = new byte[dataLength];
    int receivedBytes = 0;
    while (receivedBytes < dataLength)
    {
        receivedBytes += current.Receive(dataBuffer, receivedBytes, dataLength - receivedBytes, SocketFlags.None);
    }
    
    // 转发给接收端(直接复用收到的数据包即可)
    // receiverSocket.Send(sendBuffer, sendBuffer.Length, SocketFlags.None);
    
    // 测试保存
    ImageConverter convertData = new ImageConverter();
    Image image = (Image)convertData.ConvertFrom(dataBuffer);
    image.Save($"{senderIp}_image.png");
    Console.WriteLine($"来自 {senderIp} 的图片已保存");
}
catch (Exception ex)
{
    Console.WriteLine("处理数据失败");
    logFileWrite("处理数据失败");
    Console.WriteLine(ex.ToString());
}

关键注意事项

  • 粘包处理:Socket通信必须通过「先传长度再传内容」的方式避免粘包,确保数据包完整接收。
  • 数据完整性:接收数据时需循环读取,直到获取到指定长度的内容,防止网络波动导致数据截断。
  • IP可靠性:方案一获取的是真实连接IP,无法伪造;方案二由客户端提供IP,适合自定义标识场景,但存在伪造风险。

内容的提问来源于stack exchange,提问作者karan ugale

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 11:10:25