Socket 向服务器发送图片 图片是损坏的,如下源码所示 ,求教

那小x的传说 2014-03-19 06:42:13


Socket 向服务器发送图片 图片是损坏的 ,找不出原因,不知是不是不能添加报头字符,请高手求教,

服务端

public class SocketServer
{
Socket sRecvPic;//接收图片的socket
int recvPicPort;//接收图片端口

//建立本地socket,一直对1234端口进行侦听
public SocketServer(int recvPort)
{
recvPicPort = recvPort;
IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, recvPicPort);
sRecvPic = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
sRecvPic.Bind(localEndPoint);
sRecvPic.Listen(100);
}

public void thread()
{
while (true)
{
System.Threading.Thread.Sleep(1);//每个线程内部的死循环里面都要加个“短时间”睡眠,使得线程占用资源得到及时释放
try
{
Socket sRecvPicTemp = sRecvPic.Accept();//一直在等待socket请求,并建立一个和请求相同的socket,覆盖掉原来的socket
sRecvPicTemp.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 5000); //设置接收数据超时
sRecvPicTemp.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, 5000);//设置发送数据超时
sRecvPicTemp.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendBuffer, 1024000);//设置发送缓冲区大小--1K大小
sRecvPicTemp.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer, 1024000); //设置接收缓冲区大小


#region 先取出数据头部信息---并解析头部

byte[] recvHeadBytes = new byte[1024];//先取1K的数据,提取出数据的头部
sRecvPicTemp.Receive(recvHeadBytes, recvHeadBytes.Length, 0);
string recvStr = Encoding.UTF8.GetString(recvHeadBytes);
string[] strHeadArray = recvStr.Split(';');//PicResponse;2;94223;69228;
string strHeadCmd = strHeadArray[0];//头部命令
int picCounts = Convert.ToInt32(strHeadArray[1]) ;//数据流中包含的图片个数
int[] picLength=new int[picCounts];//每个图片的长度
for (int i = 0; i < picCounts;i++ )
{
picLength[i] = Convert.ToInt32(strHeadArray[i+2]);
}

#endregion


int offset=0;//数据头的长度
for (int k = 0; k < strHeadArray.Length - 1;k++ )
{
offset += strHeadArray[k].Length + 1;//因为后面的分号
}

int picOffset = recvHeadBytes.Length - offset;//第一张图片在提取数据头的时候已经被提取了一部分了


if (strHeadCmd == "PicResponse")
{
#region 储存图片--为了节约内存,可以每接收一次就保存一次图片
for (int i = 0; i < picCounts; i++)
{
byte[] recvPicBytes = new byte[(picLength[i])];//每次只接收一张图片

if (i == 0)//第一幅图片有一部分在提取数据头的时候已经提取过了。
{
byte[] recvFirstPicBuffer = new byte[picLength[i] - picOffset];
sRecvPicTemp.Receive(recvFirstPicBuffer, recvFirstPicBuffer.Length, 0);
for (int j = 0; j < picOffset; j++)
{
recvPicBytes[j] = recvHeadBytes[offset + j];//第一幅图片的前一部分
}

for (int j = 0; j < recvFirstPicBuffer.Length; j++)//第一张图片的后半部分
{
recvPicBytes[picOffset + j] = recvFirstPicBuffer[j];
}

//将图片写入文件
SavePicture(recvPicBytes, "-0");
}
else
{
sRecvPicTemp.Receive(recvPicBytes, recvPicBytes.Length, 0);//每次取一张图片的长度
SavePicture(recvPicBytes, "-"+i.ToString());
//将图片数据写入文件
}
}
#endregion

}

}
catch(Exception ex)
{
Console.Write(ex.Message);
}
finally
{

}
}
}

/// <summary>
/// 保存图片到指定路径
/// </summary>
/// <param name="picBytes">图片比特流</param>
/// <param name="picNum">图片编号</param>
public void SavePicture(byte[] picBytes, string picNum)
{
string filename = "receivePic";

if (!Directory.Exists("E:\\images\\"))
Directory.CreateDirectory("E:\\images\\");
if (File.Exists("E:\\images\\" + filename + picNum + ".jpg"))
return;
FileStream fs = new FileStream("E:\\images\\" + filename + picNum + ".jpg", FileMode.OpenOrCreate, FileAccess.Write);

fs.Write(picBytes, 0, picBytes.Length);
fs.Dispose();
fs.Close();
}

}
}



客户端

public class SocketClient
{
/// <summary>
/// 向远程客户端发送图片
/// </summary>
/// <param name="strRemoteIP">远程客户端IP</param>
/// <param name="sendPort">发送图片的端口</param>
public void SentPictures(string strRemoteIP, int sendPort)
// public void SentPictures(string strRemoteIP, int sendPort)
{

string path = "D:\\images\\";
string strImageTag = "image";//图片名称中包含有image的所有图片文件

try
{
string[] picFiles = Directory.GetFiles(path, strImageTag + "*", SearchOption.TopDirectoryOnly);//满足要求的文件个数

if (picFiles.Length == 0)
{
return;//没有图片,不做处理
}

long sendBytesTotalCounts = 0;//发送数据流总长度

//消息头部:命令标识+文件数目+……文件i长度+
string strMsgHead = "PicResponse;" + picFiles.Length + ";";

//消息体:图片文件流
byte[][] msgPicBytes = new byte[picFiles.Length][];
for (int j = 0; j < picFiles.Length; j++)
{
FileStream fs = new FileStream(picFiles[j].ToString(), FileMode.Open, FileAccess.Read);
BinaryReader reader = new BinaryReader(fs);
msgPicBytes[j] = new byte[fs.Length];
strMsgHead += fs.Length.ToString() + ";";
sendBytesTotalCounts += fs.Length;
reader.Read(msgPicBytes[j], 0, msgPicBytes[j].Length);
}

byte[] msgHeadBytes = Encoding.Default.GetBytes(strMsgHead);//将消息头字符串转成byte数组
sendBytesTotalCounts += msgHeadBytes.Length;
//要发送的数据流:数据头+数据体

byte[] sendMsgBytes = new byte[sendBytesTotalCounts];//要发送的总数组

for (int i = 0; i < msgHeadBytes.Length; i++)
{
sendMsgBytes[i] = msgHeadBytes[i]; //数据头
}


int index = msgHeadBytes.Length;
for (int i = 0; i < picFiles.Length; i++)
{

for (int j = 0; j < msgPicBytes[i].Length; j++)
{
sendMsgBytes[index + j] = msgPicBytes[i][j];
}
index += msgPicBytes[i].Length;
}
//程序执行到此处,带有图片信息的报文已经准备好了
//PicResponse;2;94223;69228;
//+图片1比特流+……图片2比特流

try
{
#region 发送图片
Socket sSendPic = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress ipAddress = IPAddress.Parse(strRemoteIP);//remoteip = "127.0.0.1"


try
{
sSendPic.Connect(ipAddress, sendPort);//连接无端客户端主机
sSendPic.Send(sendMsgBytes, sendMsgBytes.Length, 0);//发送本地图片
}
catch (System.Exception e)
{
System.Console.Write("SentPictures函数在建立远程连接时出现异常:" + e.Message);
}finally
{
sSendPic.Close();
}
#endregion
}
catch
{
}


}
catch(Exception ex)
{
Console.Write(ex.Message);
}

}


}


aspx.cs

public partial class JpegForSocketServer : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
int intPort =1234;//客户端一直对1234端口进行侦听---接收图片的端口
SocketServer sendPic = new SocketServer(intPort);//监听接收来自图片服务器的图片以及客户端的命令
Thread tRecvPic = new Thread(new ThreadStart(sendPic.thread));
tRecvPic.IsBackground = true;
tRecvPic.Start();
}
}
protected void Button1_Click(object sender, EventArgs e)
{ SocketClient ss = new SocketClient();
ss.SentPictures("127.0.0.1",400);
}
}



...全文
415 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
那小x的传说 2014-03-20
  • 打赏
  • 举报
回复
问题出在 这些语句 不能二次读取 sRecvPicTemp.Receive(recvPicBytes, recvPicBytes.Length, 0);//每次取一张图片的长度 SavePicture(recvPicBytes, "-"+i.ToString()); 还有就是要睡眠1秒 不然接收的图片 显示不完整个
那小x的传说 2014-03-20
  • 打赏
  • 举报
回复
引用 7 楼 sp1234 的回复:
以前,csdn页面上贴的代码会自动撑开页面宽度,那个时候我还是愿意看代码的。 现在这个csdn,一旦代码行数多了,并且宽了,我没法看代码。 因此这种帖子根本没法回。
大神,上面有个源码键,按下去就可以任您看的 ,谢谢关注啦
那小x的传说 2014-03-20
  • 打赏
  • 举报
回复

一张一张 发送 有时显示完整,有时显示只有一半,查看图片的大小节能 都是足够的 ?
  • 打赏
  • 举报
回复
以前,csdn页面上贴的代码会自动撑开页面宽度,那个时候我还是愿意看代码的。 现在这个csdn,一旦代码行数多了,并且宽了,我没法看代码。 因此这种帖子根本没法回。
本拉灯 2014-03-19
  • 打赏
  • 举报
回复
肯定是粘包了。。。
  • 打赏
  • 举报
回复
csdn的代码页面很垃圾地只能显示窄窄的页面,如果你的代码较多,并且所需页面比较宽,就不要在csdn上发代码了。
那小x的传说 2014-03-19
  • 打赏
  • 举报
回复
无语! 数据流 没流到客户端????
那小x的传说 2014-03-19
  • 打赏
  • 举报
回复
引用 2 楼 feiyun0112 的回复:
试试用winform做服务端/客户端 ***************************************************************************** 签名档: http://feiyun0112.cnblogs.com/
问题 一样存 在的 难道加入报头后 图片流会打乱了,?
feiyun0112 2014-03-19
  • 打赏
  • 举报
回复
试试用winform做服务端/客户端

*****************************************************************************
签名档: http://feiyun0112.cnblogs.com/
那小x的传说 2014-03-19
  • 打赏
  • 举报
回复
ss.SentPictures("127.0.0.1",400); 这里端口号是1234改成 ss.SentPictures("127.0.0.1",1234);

62,041

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术交流专区
javascript云原生 企业社区
社区管理员
  • ASP.NET
  • .Net开发者社区
  • R小R
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

.NET 社区是一个围绕开源 .NET 的开放、热情、创新、包容的技术社区。社区致力于为广大 .NET 爱好者提供一个良好的知识共享、协同互助的 .NET 技术交流环境。我们尊重不同意见,支持健康理性的辩论和互动,反对歧视和攻击。

希望和大家一起共同营造一个活跃、友好的社区氛围。

试试用AI创作助手写篇文章吧