客户端Socket连接,老是要重启一下网卡,客户端Socket连接才能正常呢

wen2013 2013-06-16 09:02:27
服务器有三块网卡的,134网段、10网段、外网,为什么老是要重启一下网卡,客户端Socket连接才能正常呢?请大侠帮助解答一下。

服务器上要主动建立多个客户端固定的连接到134网段的每个终端,每个客户端连接使用一个线程,在线程里这大致这样实现连接采集数据的:
1、skt := Socket(AF_INET, SOCK_STREAM, IPPROTO_IP)
2、 Connect(skt, addr, sizeof(addr))
3、循环采集数据 recv、send
4、CloseSocket(skt);
5、在主程序启动和退出时分别调用了WSAStartup(MAKEWORD(2, 2), MyWSA)、 WSACleanup()

目前问题是:
每次程序启动,刚开始能连接134网段上的终端收发数据,然后不到一分钟就这个连接就不能收发数据,线程中重新连接机制,但重新连接不上,这时连接的错误代码是10060。
这个时候我在系统中用另外的测试工具也连接不上那个终端,如果我让这个客户端线程退出,测试工具又能连接上那个终端。
如果当程序重新连接不上终端时,我禁用、再启用一下134网卡,这时连接就恢复正常了,能正常收发数据。

采集线程代码如下:
procedure TClientSocketPortThread.SocketCollect; //Socket采集
var
skt: TSOCKET; //创建Socket对象
addr: TSockAddr; //地址信息
tmpStr: string;
tModul: TContrlModule;
SocketAddr: string;
SocketPort: Integer;
SocketErroFlag: Byte;
i, CollectResult: Integer;
CollectFailCount, OpenSocketErrorCount: Integer; //采集次数, 失败次数
begin
SocketAddr := '';
SocketPort := 0;
if Pos(',', FCommPara) > 1 then
begin
try
SocketAddr := Copy(FCommPara, 1, Pos(',', FCommPara) - 1);
SocketPort := StrToInt(Copy(FCommPara, Pos(',', FCommPara) + 1, Length(FCommPara) - Pos(',', FCommPara)));
except on E: Exception do
begin
tmpStr := FName + ':' + '分解CommPara出错!' + E.Message;
OutMess(tmpStr, 'COM');
WriteSystemLog(tmpStr);
end;
end;
end;
while (not FCloseFlag) and (not Terminated) do
begin
try
ZeroMemory(@addr, sizeof(addr));
Addr.sin_family := AF_INET;
Addr.sin_addr.S_addr := inet_addr(PChar(SocketAddr));
Addr.sin_port := Htons(SocketPort);
//建立Socket句柄
UpdateListInfo(3, '准备建立Socket');
skt := Socket(AF_INET, SOCK_STREAM, IPPROTO_IP); //IPPROTO_TCP);
if (skt = INVALID_SOCKET) then
begin
mySleep(5000);
Continue;
end;
try
OpenSocketErrorCount := 0;
while (not FCloseFlag) and (not Terminated) do
begin
// 建立连接
SocketErroFlag := Connect(skt, addr, sizeof(addr));
if (SocketErroFlag <> 0) then
begin
for i := 0 to FModulList.Count - 1 do //置此串口采集所有模块采集故障
begin
tModul := FModulList[i];
tModul.SeriesCollectFailCount := tModul.SeriesCollectFailCount + 1;
if tModul.SeriesCollectFailCount >= tModul.MaxCollectFailCount then
begin
tModul.SetCollectErro;
RefreshModulImage(tModul); //刷新图标状态
end;
end;
Inc(OpenSocketErrorCount);
tmpStr := FName + ':连续' + IntToStr(OpenSocketErrorCount) + '次打开Socket连接失败! 地址:' + SocketAddr + ' 端口:' + IntToStr(SocketPort) + ' 错误代码:' + IntToStr(WSAGetLastError);
UpdateListInfo(3, '连续' + IntToStr(OpenSocketErrorCount) + '次打开Socket连接失败, 错误代码:' + IntToStr(WSAGetLastError)); //FListItem.SubItems[1] := '打开Socket连接失败';
OutMess(tmpStr, 'COM');
if not FilterSocketConnectErrorLog then
WriteSystemLog(tmpStr);
mySleep(2000);
if OpenSocketErrorCount >= 5 then //连续5次打开错误
begin
UpdateListInfo(3, tmpStr);
raise Exception.Create(tmpStr);
end;
Continue;
end;
tmpStr := FName + ':打开Socket连接成功! 地址:' + SocketAddr + ' 端口:' + IntToStr(SocketPort);
UpdateListInfo(3, '打开Socket连接成功'); //FListItem.SubItems[1] := '打开Socket连接成功';
OutMess(tmpStr, 'COM');
WriteSystemLog(tmpStr);
mySleep(1000);
//开始轮询采集
CollectFailCount := 0;
while (not FCloseFlag) and (not Terminated) do
begin
for i := 0 to FModulList.Count - 1 do
begin
tModul := FModulList[i];
tModul.Handle := skt;
UpdateListInfo(3, '空闲');
RefreshModulImage(tModul);
if (tModul.Enabeled) and (tModul.CommNo = FCommID) then
begin
tModul.ExeCmd; //先执行命令
if tModul.CollectTime > Now then //防止系统日期改变后不会采集
tModul.CollectTime := Now;
if Abs((Now - tModul.CollectTime) * 24 * 60 * 60) >= tModul.ColltIntval then //达到采集间隔执行采集
begin
UpdateListInfo(2, tModul.Name);
UpdateListInfo(3, '开始采集');
OutMess('采集模块索引号:' + IntToStr(tModul.IndexNo) + '开始采集', tModul.IndexNo);
StartCollect(tModul, CollectResult);
if CollectResult <> 0 then
begin
Inc(CollectFailCount);
UpdateListInfo(3, '采集失败');
OutMess('采集模块索引号:' + IntToStr(tModul.IndexNo) + '采集失败', tModul.IndexNo);
OutMess('采集模块索引号:' + IntToStr(tModul.IndexNo) + '开始Socket重连', tModul.IndexNo);
shutdown(skt, SD_BOTH);
Sleep(100);
raise Exception.Create('采集模块索引号:' + IntToStr(tModul.IndexNo) + '采集失败');
end
else
begin
UpdateListInfo(3, '采集完成');
OutMess('采集模块索引号:' + IntToStr(tModul.IndexNo) + '采集完成', tModul.IndexNo);
end;
mySleep(FQueryInterval);
end;
tModul.ActiveEvent;
end;
Sleep(10);
end;
if CollectFailCount >= 5 then //采集失败
begin
tmpStr := FName + ':采集失败,第' + IntToStr(CollectFailCount) + '次重新打开串口!';
OutMess(tmpStr, 'COM');
WriteSystemLog(tmpStr);
Break;
end;
Sleep(10);
end;
end;
finally
CloseSocket(skt);
end;
except on E: Exception do
WriteSystemLog(E.Message);
end;
end;
end;
...全文
357 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
Geoff08Zhang 2013-06-21
  • 打赏
  • 举报
回复
试试直接bind到要用的网卡,这有很多socket源码,你找一个试试,有没有同样的问题: http://download.csdn.net/detail/geoff08zhang/4571358
大风吹过脸颊 2013-06-21
  • 打赏
  • 举报
回复
这个有点难度,个人觉得可以尝试写代码进行判断和自动切换,避免重启网卡的问题。

1,593

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 网络通信/分布式开发
社区管理员
  • 网络通信/分布式开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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