C# Socket通讯,针对同一客户端的二次连接请求的疑问?这问题我都不知道怎么问了 ,拜托大神帮帮忙

小月还小 2018-09-14 09:59:48
第一次在这里提问好紧张,你不知道菜会不知道会被骂啊 。 我要实现的是客户端监听到服务端断线了后,就开始10秒发一起连接请求,直到服务端连接上, 与服务端连接 ,可是很明显我这个方法会一直向服务端发送套接字,这样导致服务端启动后 ,收到同一个客户端的好多个请求 ,也就是连接了好多个ip一样的客户端 ,服务端还会停止工作
 System.Timers.Timer time = new System.Timers.Timer(60000);//定时器
private void ContentServer(object source, System.Timers.ElapsedEventArgs e)
{

try
{
//定义一个套字节监听 包含3个参数(IP4寻址协议,流式连接,TCP协议)
socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

//获取文本框输入的服务端IP和Port
IPAddress serverIPAddress = IPAddress.Parse(txtIP.Text.Trim());
int serverPort = int.Parse(txtPort.Text.Trim());
IPEndPoint endpoint = new IPEndPoint(serverIPAddress, serverPort);
//向指定的ip和端口号的服务端发送连接请求 用的方法是Connect 不是Bind
socketClient.Connect(endpoint);
//创建一个新线程 用于监听服务端发来的信息
threadClient = new Thread(RecMsg);
//将窗体线程设置为与后台同步
threadClient.IsBackground = true;
//启动线程
threadClient.Start();
txtMsg.AppendText("已与服务端建立连接,可以开始通信...\r\n");
time.Enabled = false;
time.Stop();
//btnConnectToServer.Enabled = false;
}
catch (Exception)
{
txtMsg.AppendText("服务端已经断开连接,请等待...\r\n");



}

}
/// <summary>
/// 接受服务端发来信息的方法
/// </summary>
string strRecMsg;
//定义一个委托
delegate void Advice(string ss);
private void RecMsg()
{
strRecMsg = null;
while (true) //持续监听服务端发来的消息
{
strRecMsg = null;

int length = 0;
byte[] buffer = new byte[SendBufferSize];
try
{
//将客户端套接字接收到的字节数组存入内存缓冲区, 并获取其长度
length = socketClient.Receive(buffer);
}
catch (SocketException ex)
{
txtMsg.AppendText("套接字异常消息:" + ex.Message + "\r\n");
txtMsg.AppendText("服务端已断开连接\r\n");
//启用定时监听


time.Elapsed += new System.Timers.ElapsedEventHandler(ContentServer);
time.AutoReset = true ;
time.Enabled = true;



break;
}

...全文
846 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
小月还小 2018-10-10
  • 打赏
  • 举报
回复
引用 21 楼 enaking 的回复:
这个不需要用定时,因为你已经用了while。
好的 谢谢你的回复 ,已经解决
小月还小 2018-10-08
  • 打赏
  • 举报
回复
引用 17 楼 lxgmag2016 的回复:
若通讯实时要求非常高,可用发送“心跳包”的方式解决,一发一收。 在链路空闲时发。
在网路不稳定的情况下也没有影响吗?
enaking 2018-10-08
  • 打赏
  • 举报
回复
这个不需要用定时,因为你已经用了while。
enaking 2018-10-08
  • 打赏
  • 举报
回复
这个不需要用定时,因为你已经用了Timer。
lxgmag2016 2018-09-28
  • 打赏
  • 举报
回复
若通讯实时要求非常高,可用发送“心跳包”的方式解决,一发一收。
在链路空闲时发。

  • 打赏
  • 举报
回复
引用 10 楼 ly_longyue 的回复:
[quote=引用 8 楼 w5s2g0_zxy 的回复:] [quote=引用 6 楼 is_my_self 的回复:] 如果是针对一个连接成功的ip发来的联机请求你可以直接无视就好了,不要再次进行连接了。
嗯嗯 这里我解决了 ,如果客户端一直在发请求 ,而服务端还是没有反应的话 ,客户端会因为无限递归而造成停止运行,请问你知道怎么解决的吗 [/quote] 搞个 次数配置呗,重连多少次之后就不重连了。报个警啥的。[/quote] 这个方面我是用的计时器的方式,定时多久没有信息传回来说明断了,就停止发送信息并报警
飘渺一方 2018-09-25
  • 打赏
  • 举报
回复
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace GemCommon.Net { /// <summary> /// 登录服务器 /// </summary> public class Decoding_LS { /// <summary> /// 服务器接收到完整报文事件 /// </summary> public static event SessionEvent RecvData; /// <summary> /// 读取连接负载服务器新发送的数据 /// </summary> /// <param name="state"></param> public static void tcp_ReadBufferChanged(GemCommon.Net.Session state) { int RepStart = -1;//报文开始位置 int RepEnd = 0;//报文结束位置 do { //查找报文头 RepStart = state.Context.IndexOf("<TXCS", RepEnd); if (RepStart >= 0) { RepEnd = state.Context.IndexOf("/TXCS>", RepStart); //如果报文接收完整 if (RepEnd > RepStart) { state.Data = state.Context.Substring(RepStart, RepEnd - RepStart + 6); state.Context = state.Context.Remove(0, RepEnd); //发布一个报文消息 if (RecvData != null) { try { RecvData(state); } catch (Exception ex) { System.Windows.Forms.MessageBox.Show(ex.Message + System.Environment.NewLine + ex.StackTrace); GemCommon.AppLog.AddErrLog("解析崩溃了:" + ex.Message + System.Environment.NewLine + ex.StackTrace); } } RepEnd = 0; } else { //如果报文接收不完整则退出 break; } } else { //找不到报文开头则退出 break; } } while (state.Context != ""); } /// <summary> /// 解析连接负载服务器发送的完整报文 /// </summary> /// <param name="state"></param> public static void TcpServer_HaveNewReport(GemCommon.Net.Session state) { string jsonResult = ""; string data = state.Data; string xor = data.Substring(data.IndexOf("xor=") + 5, 2); int len = Convert.ToInt32(getValue(data, "len=")); string json = data.Substring(data.IndexOf("data=") + 6, len); if (GemCommon.CommonTools.XorVerification(json) == xor) { GemCommon.Model.StandardModel sm = new Model.StandardModel(); sm = (GemCommon.Model.StandardModel)GemCommon.CommonTools.LoadFromJson(json, sm.GetType()); switch (sm.FunName) { case "LinkName"://设置连接名 state.SessionName = sm.GetStr("LinkName"); break; case "LS_Login"://登录 jsonResult = Login(sm); state.Send(jsonResult); break; default: Model.StandardModel result = new Model.StandardModel(); result.ReportID = sm.ReportID; result.SessionID = sm.SessionID; result.FunName = "ErrFunType"; result.FunType = "ST"; result.AddParm("Msg", "功能名错误!"); jsonResult = GemCommon.CommonTools.ToJsonString(result, result.GetType()); state.Send(jsonResult); break; } } } /// <summary> /// 用户登录 /// </summary> /// <param name="state"></param> /// <param name="sm"></param> /// <returns></returns> private static string Login(Model.StandardModel sm) { Model.StandardModel result = new Model.StandardModel(); result.SessionID = sm.SessionID; result.ReportID = sm.ReportID; if (sm.FunType == "User_Pwd") { string userName = sm.GetStr("LoginName"); string pwd = sm.GetStr("LoginPWD"); //pwd = GemCommon.CommonTools.GetMD5(pwd.Trim()); if (userName != null && pwd != null) { GameserverModel.UserLogin ul = LoginServer.Program.UserDic_Name[userName]; if (ul != null) { if (ul.LoginPWD.Trim() == pwd.Trim()) { result.FunName = "LoginSuccess"; result.FunType = "ST"; result.AddParm("UserID", (int)ul.UserID.Value); result.AddParm("LastMarSerID", ul.LastMarSerID.Value); result.AddParm("MarSerList", ul.MarSerList); } else//if (ul.LoginPWD == pwd) { result.FunName = "LoginFailure"; result.FunType = "ST"; result.AddParm("Msg", "用户名或密码错误!"); } } else// (ul != null) { result.FunName = "LoginFailure"; result.FunType = "ST"; result.AddParm("Msg", "用户名或密码错误!"); } } else //(userName != null && pwd != null) { result.FunName = "LoginFailure"; result.FunType = "ST"; result.AddParm("Msg", "传递参数为null!"); } } else// (sm.FunType == "User_Pwd") { result.FunName = "ErrFunType"; result.FunType = "ST"; result.AddParm("Msg", "功能类型错误!"); } return GemCommon.CommonTools.ToJsonString(result, result.GetType()); } private static string getValue(string data, string key) { int begin = 0; int end = 0; begin = data.IndexOf(key) + key.Length + 1; end = data.IndexOf("\"", begin); return data.Substring(begin, end - begin); } } }
_孤星 2018-09-21
  • 打赏
  • 举报
回复
重连之前将原有Socket关闭并释放,这样重连的时候保证本地只有一个申请连接就好
小月还小 2018-09-21
  • 打赏
  • 举报
回复
引用 11 楼 u012494939 的回复:
重连之前将原有Socket关闭并释放,这样重连的时候保证本地只有一个申请连接就好
额 具体怎么实现啊? 感觉我整个设计思路不好做啊
E次奥 2018-09-20
  • 打赏
  • 举报
回复
1、Socket链接得有次数限制 2、网络断了就不要发送链接 3、每次检测发送链接前检测当前Socket状态,如果是“正在链接”或者“Socket正常”就不要再发送链接了;
小月还小 2018-09-20
  • 打赏
  • 举报
回复
引用 6 楼 is_my_self 的回复:
如果是针对一个连接成功的ip发来的联机请求你可以直接无视就好了,不要再次进行连接了。
嗯嗯 这里我解决了 ,如果客户端一直在发请求 ,而服务端还是没有反应的话 ,客户端会因为无限递归而造成停止运行,请问你知道怎么解决的吗
龍月 2018-09-20
  • 打赏
  • 举报
回复
引用 8 楼 w5s2g0_zxy 的回复:
[quote=引用 6 楼 is_my_self 的回复:]
如果是针对一个连接成功的ip发来的联机请求你可以直接无视就好了,不要再次进行连接了。



嗯嗯 这里我解决了 ,如果客户端一直在发请求 ,而服务端还是没有反应的话 ,客户端会因为无限递归而造成停止运行,请问你知道怎么解决的吗 [/quote]
搞个 次数配置呗,重连多少次之后就不重连了。报个警啥的。
xian_wwq 2018-09-15
  • 打赏
  • 举报
回复
可以参考这个
https://download.csdn.net/download/xian_wwq/9636584
小月还小 2018-09-14
  • 打赏
  • 举报
回复
自己顶顶 等等等
小月还小 2018-09-14
  • 打赏
  • 举报
回复
直接不用定时 把连接方法放在catch里?
  • 打赏
  • 举报
回复
你自己想想看,如果你定上闹钟说每1小时提醒你一次某事情,只要上一次闹钟就行了!

你还要无限循环重复这个动做吗?这是什么逻辑?
小月还小 2018-09-14
  • 打赏
  • 举报
回复
引用 2 楼 sp1234 的回复:
你自己想想看,如果你定上闹钟说每1小时提醒你一次某事情,只要上一次闹钟就行了!

你还要无限循环重复这个动做吗?这是什么逻辑?

大神说的对,但是应该放在哪里呢 , 小女子求教
  • 打赏
  • 举报
回复
定时机制本身就是连续工作的。在定时器注册的语句外边再来个 while 循环,纯粹是胡闹。
  • 打赏
  • 举报
回复
如果是针对一个连接成功的ip发来的联机请求你可以直接无视就好了,不要再次进行连接了。

110,545

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

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