C# Socket 问题 在线等急求大神指点 socket多线程内存通信delegate 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 private void COMM() { try { IPAddress ipaddress = IPAddress.Parse(acustatus.Acuip);//服务器IP IPEndPoint serverIP = new IPEndPoint(ipaddress, acustatus.Port); send = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); send.Connect(serverIP); } catch (Exception ex) { } }就是在连接时报错, 我的想法是我用的是多线程 ,同时每个线程都是创建的独立的socket连接 这样的应该里面有一个SOCKET 连接出错了,应该 不会影响到别的连接才对呀,但是却出错了,相互影响. private void COMM(objcet obj) {string IP=obj.ToString(); try { IPAddress ipaddress = IPAddress.Parse(acustatus.Acuip);//服务器IP IPEndPoint serverIP = new IPEndPoint(ipaddress, acustatus.Port); send = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); send.Connect(serverIP); } catch (Exception ex) { } }启动线程时:Thread thread = new Thread(new ThreadStart(COMM)); thread.IsBackground = true; thread.Start(IP); 你也可以将IP和Port都放到一个字符串里传递,或先放到一个结构里,然后传递总之你得给线程传递参数 private void COMM(objcet obj) {string IP=obj.ToString(); try { IPAddress ipaddress = IPAddress.Parse(acustatus.Acuip);//服务器IP IPEndPoint serverIP = new IPEndPoint(ipaddress, acustatus.Port); send = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); send.Connect(serverIP); } catch (Exception ex) { } }启动线程时:Thread thread = new Thread(new ThreadStart(COMM)); 使用了参数以后这个地方就报错了. thread.IsBackground = true; thread.Start(IP); Thread thread = new Thread(new ThreadStart(COMM)); 改成了Thread thread = new Thread(COMM)); 以后可以运行了,但是还是以前一样,只要有超过,10台以上的服务器没有连接成功,还是会不停的涨内,存同时别的能连接的也会连接不上. IP的实际意义就是IPEndPoint serverIP = new IPEndPoint(ipaddress, acustatus.Port);就是说,你的线程函数现在是个无参数的函数,那么其实所有线程(不管你到底开了10个还是100个),其实都是连接的同一个IP(服务端)你必须给每个线程函数传递参数,让每个线程去连接对应的IP 你好,我现在改成这样了 private void COMM(objcet obj) { Acustatus acustatus=(Acustatus)obj; try { IPAddress ipaddress = IPAddress.Parse(acustatus.Acuip);//服务器IP IPEndPoint serverIP = new IPEndPoint(ipaddress, acustatus.Port); send = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); send.Connect(serverIP); } catch (Exception ex) { } } 但是上面的问题还是同样的存在, 同时我在另一个方法里调用, 另一个异步线程去 创建socket的时 都有单独传 IP 过去的, while (sendstatus) { Thread.Sleep(10); if( AcuTable.Count >0) { for (int i = 0; i < AcuTable.Count; i++) { ACUStruct status = (ACUStruct)AcuTable[i]; lock (AcuTable) { AcuTable.RemoveAt(i); } status.Timesout = status.Timesout + 1; if (status.Acutime == 0) { WeSafeSend wsend = new WeSafeSend(status); Thread wth = new Thread(new ThreadStart(wsend.SendData)); wth.IsBackground = true; wth.Start(); } else { status.Acutime = status.Acutime - 1; lock (AcuTable) { AcuTable.Add(status); } } } }每次新生一个SOCKET的都有传送不同的,ACUStruct 对象,这个对象里装的就是IP等参数. if (statusconn) { if (acustatus.Conncount == 0 && acustatus.Acuconnstatus == 0)//第一次连接成功00 00 15 00 00 00 00 20 14 11 23 21 10 50 01 50 0 { string time = DateTime.Now.Year.ToString() + TwoStrLeng(DateTime.Now.Month.ToString()) + TwoStrLeng(DateTime.Now.Day.ToString()) + TwoStrLeng(DateTime.Now.Hour.ToString()) + TwoStrLeng(DateTime.Now.Minute.ToString()) + TwoStrLeng(DateTime.Now.Second.ToString()); tcppro.InsertUploadlog("00001500000000" + time + "001500", ports);//写入在线日志 tcppro.UpdateACUConnStatus(1, ports);//更新状态为连接 }这里是连接日志的写入点,也就是说我连接上以后,就会把连接成功的状态写入日志下面是失败以后写的日志代码 else { if (acustatus.Outtimecount == 5)//&& acustatus.Acuconnstatus == 0 { acustatus.Conncount = 0; acustatus.Acuconnstatus = 0; tcppro.UpdateACUConnStatus(2, ports);//更新状态为断开 string time = DateTime.Now.Year.ToString() + TwoStrLeng(DateTime.Now.Month.ToString()) + TwoStrLeng(DateTime.Now.Day.ToString()) + TwoStrLeng(DateTime.Now.Hour.ToString()) + TwoStrLeng(DateTime.Now.Minute.ToString()) + TwoStrLeng(DateTime.Now.Second.ToString()); tcppro.InsertUploadlog("00001400000000" + time + "001400", ports);//写入脱机日志 } 建议你还是把逻辑缕清楚了先你现在是循环启动线程,然后线程里又启动线程然后又加入了一堆lock和同步既然想同时连接多个服务端,就不要胡乱同步了如果是想把线程连接结果输出,你可以使用委托,搜一搜:委托操作UI把顺序执行的思想先丢弃,然后再研究如果并行执行,否则做出来的就是个不伦不类的怪物程序 private ACUStruct acustatus;你这玩意根本不是数组,它全局只有一个你是如何保证"每个线程里传入一个单独的acustatus实例"的???你这不是在一个地方改了,所有线程里用的就都变了吗 可以说,你这个问题跟标题严重不符根本不是socket的问题,而是你根本不知道多线程应该怎么用还是先恶补一下为好 代码太杂了。 先改改吧:1: new Thread 不能乱用,这个是最消耗资源的代码。2:你用的方法都是同步函数,使用信号量allDone 没有意义,删除它,按异常逻辑走。3:多线程操作大部分都在浪费内存,简化程序,只允许一个地方出现 new Thread 。 如何用最高的权限删除所有的MSMQ的priavte的内容 求教啊~ 有关DataGridView的问题 如何根据周数获取月份 求助:MDI窗体中,父窗体是怎么样感应到子窗体中菜单变化的 两个100分问一个问题,ViewState的问题,我在同一个页面的usercontrol里引用该页面的另一个usercontrol里的ViewState,怎么得不到值? 各位帮忙,着急!搞不定就会不了家了 更新数据库时当变量包含“'”时会出错的问题 如何在MDI主窗体的toolbar上执行子窗体的程序?在线等........ devexpress 求助 C# 进制转换问题! 小女子请教线程同步的问题~
{
try
{
IPAddress ipaddress = IPAddress.Parse(acustatus.Acuip);//服务器IP
IPEndPoint serverIP = new IPEndPoint(ipaddress, acustatus.Port);
send = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
send.Connect(serverIP); }
catch (Exception ex)
{
}
}
就是在连接时报错,
{
string IP=obj.ToString();
try
{
IPAddress ipaddress = IPAddress.Parse(acustatus.Acuip);//服务器IP
IPEndPoint serverIP = new IPEndPoint(ipaddress, acustatus.Port);
send = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
send.Connect(serverIP);
}
catch (Exception ex)
{
}
}
启动线程时:
Thread thread = new Thread(new ThreadStart(COMM));
thread.IsBackground = true;
thread.Start(IP);
总之你得给线程传递参数
{
string IP=obj.ToString();
try
{
IPAddress ipaddress = IPAddress.Parse(acustatus.Acuip);//服务器IP
IPEndPoint serverIP = new IPEndPoint(ipaddress, acustatus.Port);
send = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
send.Connect(serverIP);
}
catch (Exception ex)
{
}
}
启动线程时:
Thread thread = new Thread(new ThreadStart(COMM)); 使用了参数以后这个地方就报错了. thread.IsBackground = true;
thread.Start(IP);
IPEndPoint serverIP = new IPEndPoint(ipaddress, acustatus.Port);
就是说,你的线程函数现在是个无参数的函数,那么其实所有线程(不管你到底开了10个还是100个),其实都是连接的同一个IP(服务端)
你必须给每个线程函数传递参数,让每个线程去连接对应的IP
private void COMM(objcet obj)
{
Acustatus acustatus=(Acustatus)obj;
try
{
IPAddress ipaddress = IPAddress.Parse(acustatus.Acuip);//服务器IP
IPEndPoint serverIP = new IPEndPoint(ipaddress, acustatus.Port);
send = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
send.Connect(serverIP);
}
catch (Exception ex)
{
}
}
但是上面的问题还是同样的存在,
while (sendstatus)
{
Thread.Sleep(10);
if( AcuTable.Count >0)
{
for (int i = 0; i < AcuTable.Count; i++)
{
ACUStruct status = (ACUStruct)AcuTable[i];
lock (AcuTable)
{
AcuTable.RemoveAt(i);
}
status.Timesout = status.Timesout + 1;
if (status.Acutime == 0)
{
WeSafeSend wsend = new WeSafeSend(status);
Thread wth = new Thread(new ThreadStart(wsend.SendData));
wth.IsBackground = true;
wth.Start();
}
else
{
status.Acutime = status.Acutime - 1;
lock (AcuTable)
{
AcuTable.Add(status);
}
}
}
}
每次新生一个SOCKET的都有传送不同的,ACUStruct 对象,这个对象里装的就是IP等参数.
{
if (acustatus.Conncount == 0 && acustatus.Acuconnstatus == 0)//第一次连接成功00 00 15 00 00 00 00 20 14 11 23 21 10 50 01 50 0
{
string time = DateTime.Now.Year.ToString() + TwoStrLeng(DateTime.Now.Month.ToString()) + TwoStrLeng(DateTime.Now.Day.ToString())
+ TwoStrLeng(DateTime.Now.Hour.ToString()) + TwoStrLeng(DateTime.Now.Minute.ToString()) + TwoStrLeng(DateTime.Now.Second.ToString());
tcppro.InsertUploadlog("00001500000000" + time + "001500", ports);//写入在线日志
tcppro.UpdateACUConnStatus(1, ports);//更新状态为连接
}
这里是连接日志的写入点,也就是说我连接上以后,就会把连接成功的状态写入日志
下面是失败以后写的日志代码
else
{
if (acustatus.Outtimecount == 5)//&& acustatus.Acuconnstatus == 0
{
acustatus.Conncount = 0;
acustatus.Acuconnstatus = 0;
tcppro.UpdateACUConnStatus(2, ports);//更新状态为断开
string time = DateTime.Now.Year.ToString() + TwoStrLeng(DateTime.Now.Month.ToString()) + TwoStrLeng(DateTime.Now.Day.ToString())
+ TwoStrLeng(DateTime.Now.Hour.ToString()) + TwoStrLeng(DateTime.Now.Minute.ToString()) + TwoStrLeng(DateTime.Now.Second.ToString());
tcppro.InsertUploadlog("00001400000000" + time + "001400", ports);//写入脱机日志
}
你现在是循环启动线程,然后线程里又启动线程
然后又加入了一堆lock和同步既然想同时连接多个服务端,就不要胡乱同步了
如果是想把线程连接结果输出,你可以使用委托,搜一搜:委托操作UI
把顺序执行的思想先丢弃,然后再研究如果并行执行,否则做出来的就是个不伦不类的怪物程序
你这玩意根本不是数组,它全局只有一个
你是如何保证"每个线程里传入一个单独的acustatus实例"的???
你这不是在一个地方改了,所有线程里用的就都变了吗
根本不是socket的问题,而是你根本不知道多线程应该怎么用
还是先恶补一下为好
1: new Thread 不能乱用,这个是最消耗资源的代码。
2:你用的方法都是同步函数,使用信号量allDone 没有意义,删除它,按异常逻辑走。
3:多线程操作大部分都在浪费内存,简化程序,只允许一个地方出现 new Thread 。