private void ScanIPTotal()
{
for (int i = 0; i < scanThreads.Length; i++)
{
scanThreads[i] = new Thread(new ThreadStart(ScanIP));
scanThreads[i].IsBackground = true;
scanThreads[i].Start();
}
WaitIPScanFinish:
Thread.Sleep(200);
for (int i = 0; i < scanThreads.Length; i++)
{
if (scanThreads[i].ThreadState != ThreadState.Aborted && scanThreads[i].ThreadState != ThreadState.Stopped)
{
Thread.Sleep(200);
goto WaitIPScanFinish; // 死循环等待所有扫描子线程结束
}
else
{
}
}
ShowIPScanResult myShowIPScanResult = new ShowIPScanResult(Update_FinishIPScan);
this.Invoke(myShowIPScanResult);
}
private void ScanIP()
{
ScanLeftIP:
string tmpIP="";
lock (needScanIP)
{
if (needScanIP.Count > 0)
{
tmpIP = needScanIP[needScanIP.Count - 1].ToString();
needScanIP.RemoveAt(needScanIP.Count - 1);
}
else
{
}
}
if (tmpIP != "")
{
if (PingHost.IpOnLine(tmpIP)==true) // 判断在线
{
lock(onlineIP) // 锁住变量比锁住UI控件容易
{
onlineIP.Add(tmpIP+"在线");
ShowIPScanResult uplsB = new ShowIPScanResult(Update_lsB_LiveHost);// 子线程一般不能直接修改UI,所以用这块委托(放外面可能会乱了)
this.Invoke(uplsB);
}
}
else
{
lock (onlineIP) // 锁住变量比锁住UI控件容易
{
onlineIP.Add(tmpIP + "未在线");
ShowIPScanResult uplsB = new ShowIPScanResult(Update_lsB_LiveHost);// 子线程一般不能直接修改UI,所以用这块委托(放外面可能会乱了)
this.Invoke(uplsB);
}
}
scanedIPCount ++;
ShowIPScanResult upproBar = new ShowIPScanResult(Update_proBar_IPscan);
this.Invoke(upproBar);
goto ScanLeftIP; // 死循环等待所有IP被扫描子完了,否则继续扫
}
else
{
}
}代码是扫描1-255,在线IP,问题是:9是在线IP,扫描1-8,没问题未在线,但是扫描1-9,就变成全部在线了。
容易造成死循环
改用标记flag来标记线程情况
又仔细审了下代码,看懂是所有线程共同扫描一个IP集,每个线程扫描这个IP集的独立子集,从代码上看没有看到问题。所以同意7L意见,怀疑PingHost.IpOnLine。。
{
try
{
byte[] data = new byte[1024];
int receive;
Socket host = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.Icmp);
IPEndPoint iep = new IPEndPoint(IPAddress.Parse(des_ip), 0);
EndPoint ep = (EndPoint)iep;
ICMP packet = new ICMP();
packet.Type = 0x08;
packet.Code = 0x00;
packet.Checksum = 0;
Buffer.BlockCopy(BitConverter.GetBytes((short)1), 0, packet.Message, 0, 2);
Buffer.BlockCopy(BitConverter.GetBytes((short)1), 0, packet.Message, 2, 2);
data = Encoding.ASCII.GetBytes("test packet");
Buffer.BlockCopy(data, 0, packet.Message, 4, data.Length);
packet.MessageSize = data.Length + 4;
int packetsize = packet.MessageSize + 4;
UInt16 chcksum = packet.getChecksum();
packet.Checksum = chcksum;
host.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 3000);
host.SendTo(packet.getBytes(), packetsize, SocketFlags.None, iep);
data = new byte[1024];
receive = host.ReceiveFrom(data, ref ep);
host.Close();
return true;
}
catch
{
return false;
}
}
}
public class ICMP
{
public byte Type;
public byte Code;
public UInt16 Checksum;
public int MessageSize;
public byte[] Message = new byte[1024];
public ICMP()
{
}
public ICMP(byte[] data, int size)
{
Type = data[20];
Code = data[21];
Checksum = BitConverter.ToUInt16(data, 22);
MessageSize = size - 24;
Buffer.BlockCopy(data, 24, Message, 0, MessageSize);
}
public byte[] getBytes()
{
byte[] data = new byte[MessageSize + 9];
Buffer.BlockCopy(BitConverter.GetBytes(Type), 0, data, 0, 1);
Buffer.BlockCopy(BitConverter.GetBytes(Code), 0, data, 1, 1);
Buffer.BlockCopy(BitConverter.GetBytes(Checksum), 0, data, 2, 2);
Buffer.BlockCopy(Message, 0, data, 4, MessageSize);
return data;
}
public UInt16 getChecksum()
{
UInt32 chcksm = 0;
byte[] data = getBytes();
int packetsize = MessageSize + 8;
int index = 0;
while (index < packetsize)
{
chcksm += Convert.ToUInt32(BitConverter.ToInt16(data, index));
index += 2;
}
chcksm = (chcksm >> 16) + (chcksm & 0xffff);
chcksm += (chcksm >> 16);
return (UInt16)(~chcksm);
}
private void ScanIP()
{
ScanLeftIP:
string tmpIP="";
lock (needScanIP)
{
if (needScanIP.Count > 0)
{
tmpIP = needScanIP[needScanIP.Count - 1].ToString();
needScanIP.RemoveAt(needScanIP.Count - 1);
}
else
{
}if (tmpIP != "")
{
if (PingHost.IpOnLine(tmpIP)==true) // 判断在线
{
lock(onlineIP) // 锁住变量比锁住UI控件容易
{
onlineIP.Add(tmpIP+"在线");
ShowIPScanResult uplsB = new ShowIPScanResult(Update_lsB_LiveHost);// 子线程一般不能直接修改UI,所以用这块委托(放外面可能会乱了)
this.Invoke(uplsB);
}
}
else
{
lock (onlineIP) // 锁住变量比锁住UI控件容易
{
onlineIP.Add(tmpIP + "未在线");
ShowIPScanResult uplsB = new ShowIPScanResult(Update_lsB_LiveHost);// 子线程一般不能直接修改UI,所以用这块委托(放外面可能会乱了)
this.Invoke(uplsB);
}
}
scanedIPCount ++;
ShowIPScanResult upproBar = new ShowIPScanResult(Update_proBar_IPscan);
this.Invoke(upproBar);
goto ScanLeftIP; // 死循环等待所有IP被扫描子完了,否则继续扫
}
else
{
} }
}
程序本来的意图是通过 多线程 并行处理 needScanIP,提高效率。 可现在每个线程 通过 lock 独占共享资源,没有达到 并行的效果吧?