C# Socket重发一帖 关于Socket客户端多次发送数据的问题

SomethingJack 2014-08-21 03:26:18
Scoket客户端这边的层次结构是这样的。

我需要一次连接之后发送多次数据包 让服务器多次返回来.保持长连接循环接收.

1 登录数据包
               byte[] bs = Encoding.ASCII.GetBytes(sendStr);
Console.WriteLine("Send Message");
c.Send(bs, bs.Length, 0);//发送测试信息
string recvStr = "";
byte[] recvBytes = new byte[1024];
int bytes;
bytes = c.Receive(recvBytes, recvBytes.Length, 0);//从服务器端接受返回信息
recvStr += Encoding.ASCII.GetString(recvBytes, 0, bytes);

此时recvStr 返回一个状态 如果服务器返回成功,那么我继续接下来发送第2个指令,然后再返回一个东西,判断再类推.我想知道

我上面的代码是不是只有写一次就够i了 最终到最后我索需要的就是最后那条指令返回的recvStr ?
...全文
994 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
GDY__GDY 2017-03-29
  • 打赏
  • 举报
回复
引用 6 楼 sp1234 的回复:
[quote=引用 楼主 SomethingJack 的回复:] Scoket客户端这边的层次结构是这样的。 我需要一次连接之后发送多次数据包 让服务器多次返回来.保持长连接循环接收. 1 登录数据包
               byte[] bs = Encoding.ASCII.GetBytes(sendStr);
                Console.WriteLine("Send Message");
                c.Send(bs, bs.Length, 0);//发送测试信息
                string recvStr = "";
                byte[] recvBytes = new byte[1024];
                int bytes;
                bytes = c.Receive(recvBytes, recvBytes.Length, 0);//从服务器端接受返回信息
                recvStr += Encoding.ASCII.GetString(recvBytes, 0, bytes);
此时recvStr 返回一个状态 如果服务器返回成功,那么我继续接下来发送第2个指令,然后再返回一个东西,判断再类推.我想知道 我上面的代码是不是只有写一次就够i了 最终到最后我索需要的就是最后那条指令返回的recvStr ?
你的这个设计完全不上道。针对你的描述我告诉几个要点: 1. 不要瞎抛出什么“socket”这个字眼儿来,好像挺厉害似地。实际上懂行的人一看你连“到底是哪一种协议的socket”都没有区分出来,就知道你是稀里糊涂的。socket是十几种不同的通讯方式的统一的处理接口,如果你使用基础的tcp,与使用udp相比,那么你的程序就应该是不一样的。所以你只是扔出一个“socket名词儿”来,那只能在侃大山的时候去摆摆乌龙,一旦说到具体的代码,你就不能仅仅说个“socket”这个词儿,你必须说明到底是什么协议。 既然你说的是“长连接”,下面就是假设你说的是tcp长连接(其它协议下的写法不谈)。 2. Stream收发不可能保证一次接收到所有字节,因此不可能使用一个 c.Receive(recvBytes, recvBytes.Length, 0) 语句就当是收到了完整消息。数据必须连续接收,直到你收到了并且解析出了消息结束位置。否则这条语句后边的代码就完全不可信了。 3. 长连接本身不是什么“发送一条消息,等待返回,再发送下一条”。你应该自己设计消息信令格式,其中每个消息都有一个编号/序号。那么客户端中的并行的不许多线程程序可以同时发送10条命令,然后服务器可以以任意次序返回命令结果,客户端然后回调客户端发送线程以前注册的回调方法。这就好像一栋楼里的许多人可以同时给同一个店铺下订单,然后店铺给客户在不同时间、通过同一个快递员取来包裹,快递员知道包裹分别该回给谁。如果有业务逻辑上的先后次序,那么是这种“回调”设计上的先后次序,绝不是发送消息和接收返回消息上有什么先后次序。发送和返回,是可以打乱次序的。 看你写了一些帖子,关于通讯的。但是我觉得你没有什么进步。建议你去做这方面的开发,找一个正规公司。如果没有,那么就先不要研究这些东西了。这些本应该是上午半个小时学会的东西,不应该反复纠结。[/quote]你要是遇到了能解决就告诉他一声,不会就别喷人家,我感觉楼主说的也没啥问题啊,一个socket多次发送数据有问题么?现在我也遇到一个socket第二次数据发送不出去的问题,你好好看人家的描述没有啊,一副高手的样子,真正没看懂的是你吧,看你在园子里这么热心的帮助大家我都不愿意喷你,其实你原来也帮过我,你咋学成这样了....
wenbin 2014-08-22
  • 打赏
  • 举报
回复
还需注意一点的事情是,服务器不会主动给你发数据, 你需要请求,那么就需要请求的数据格式,和具体的指令。
wenbin 2014-08-22
  • 打赏
  • 举报
回复

public int Receive(byte[] buffer, int length) {
            if (!m_isConnect) {
                return -1;
            }

            int readed = 0;
            int ret = 0;
            try {
                do {
                    ret = m_client.Receive(buffer, readed, length - readed, SocketFlags.None);
                    if (ret <= 0) {
                        Log.InfoFormat(this, "remote closed");
                        Close();
                        return -1;
                    }
                    readed += ret;
                } while (readed < length);
            } catch (Exception ee) {
                Log.Error(this, ee);
                Close();
                return -1;
            }

            return readed;
        }
使用方法:

public T Receive<T>() where T : struct {
            byte[] buffer = new byte[4];
            int ret = Receive(buffer, buffer.Length);
            if (ret <= 0) {
                return default(T);
            }

            int length = BitConverter.ToInt32(buffer, 0);
            buffer = new byte[length];
            ret = Receive(buffer, length);
            if (ret <= 0) {
                return default(T);
            }

            return buffer.BytesToStruct<T>();
        }
以上是基于Length Type Data方式完成
  • 打赏
  • 举报
回复
引用 楼主 SomethingJack 的回复:
Scoket客户端这边的层次结构是这样的。 我需要一次连接之后发送多次数据包 让服务器多次返回来.保持长连接循环接收. 1 登录数据包
               byte[] bs = Encoding.ASCII.GetBytes(sendStr);
                Console.WriteLine("Send Message");
                c.Send(bs, bs.Length, 0);//发送测试信息
                string recvStr = "";
                byte[] recvBytes = new byte[1024];
                int bytes;
                bytes = c.Receive(recvBytes, recvBytes.Length, 0);//从服务器端接受返回信息
                recvStr += Encoding.ASCII.GetString(recvBytes, 0, bytes);
此时recvStr 返回一个状态 如果服务器返回成功,那么我继续接下来发送第2个指令,然后再返回一个东西,判断再类推.我想知道 我上面的代码是不是只有写一次就够i了 最终到最后我索需要的就是最后那条指令返回的recvStr ?
你的这个设计完全不上道。针对你的描述我告诉几个要点: 1. 不要瞎抛出什么“socket”这个字眼儿来,好像挺厉害似地。实际上懂行的人一看你连“到底是哪一种协议的socket”都没有区分出来,就知道你是稀里糊涂的。socket是十几种不同的通讯方式的统一的处理接口,如果你使用基础的tcp,与使用udp相比,那么你的程序就应该是不一样的。所以你只是扔出一个“socket名词儿”来,那只能在侃大山的时候去摆摆乌龙,一旦说到具体的代码,你就不能仅仅说个“socket”这个词儿,你必须说明到底是什么协议。 既然你说的是“长连接”,下面就是假设你说的是tcp长连接(其它协议下的写法不谈)。 2. Stream收发不可能保证一次接收到所有字节,因此不可能使用一个 c.Receive(recvBytes, recvBytes.Length, 0) 语句就当是收到了完整消息。数据必须连续接收,直到你收到了并且解析出了消息结束位置。否则这条语句后边的代码就完全不可信了。 3. 长连接本身不是什么“发送一条消息,等待返回,再发送下一条”。你应该自己设计消息信令格式,其中每个消息都有一个编号/序号。那么客户端中的并行的不许多线程程序可以同时发送10条命令,然后服务器可以以任意次序返回命令结果,客户端然后回调客户端发送线程以前注册的回调方法。这就好像一栋楼里的许多人可以同时给同一个店铺下订单,然后店铺给客户在不同时间、通过同一个快递员取来包裹,快递员知道包裹分别该回给谁。如果有业务逻辑上的先后次序,那么是这种“回调”设计上的先后次序,绝不是发送消息和接收返回消息上有什么先后次序。发送和返回,是可以打乱次序的。 看你写了一些帖子,关于通讯的。但是我觉得你没有什么进步。建议你去做这方面的开发,找一个正规公司。如果没有,那么就先不要研究这些东西了。这些本应该是上午半个小时学会的东西,不应该反复纠结。
SomethingJack 2014-08-22
  • 打赏
  • 举报
回复
引用 4 楼 wodegege10 的回复:
还需注意一点的事情是,服务器不会主动给你发数据, 你需要请求,那么就需要请求的数据格式,和具体的指令。
我现在就是这样处理的 只不过我需要的是多次发送多次接收 这样是不是只建立一次连接就行了?
SomethingJack 2014-08-21
  • 打赏
  • 举报
回复
引用 1 楼 xian_wwq 的回复:
[quote=引用 楼主 SomethingJack 的回复:] Scoket客户端这边的层次结构是这样的。 我需要一次连接之后发送多次数据包 让服务器多次返回来.保持长连接循环接收. 1 登录数据包
               byte[] bs = Encoding.ASCII.GetBytes(sendStr);
                Console.WriteLine("Send Message");
                c.Send(bs, bs.Length, 0);//发送测试信息
                string recvStr = "";
                byte[] recvBytes = new byte[1024];
                int bytes;
                bytes = c.Receive(recvBytes, recvBytes.Length, 0);//从服务器端接受返回信息
                recvStr += Encoding.ASCII.GetString(recvBytes, 0, bytes);
此时recvStr 返回一个状态 如果服务器返回成功,那么我继续接下来发送第2个指令,然后再返回一个东西,判断再类推.我想知道 我上面的代码是不是只有写一次就够i了 最终到最后我索需要的就是最后那条指令返回的recvStr ?
有可能需要的数据一次Receive后就可以得到,也有可能接收的数据长度不够,这样就需要把数据暂存下,等下次接受后,通过拼包来获取足够的数据。 目前的处理逻辑会导致有的时候正常,有的时候异常。 正确的处理是在这里进行循环,如果接收足够,则跳出循环,继而解析数据, 否则继续接收。 [/quote] 能不能给出代码作为说明?
xian_wwq 2014-08-21
  • 打赏
  • 举报
回复
引用 楼主 SomethingJack 的回复:
Scoket客户端这边的层次结构是这样的。 我需要一次连接之后发送多次数据包 让服务器多次返回来.保持长连接循环接收. 1 登录数据包
               byte[] bs = Encoding.ASCII.GetBytes(sendStr);
                Console.WriteLine("Send Message");
                c.Send(bs, bs.Length, 0);//发送测试信息
                string recvStr = "";
                byte[] recvBytes = new byte[1024];
                int bytes;
                bytes = c.Receive(recvBytes, recvBytes.Length, 0);//从服务器端接受返回信息
                recvStr += Encoding.ASCII.GetString(recvBytes, 0, bytes);
此时recvStr 返回一个状态 如果服务器返回成功,那么我继续接下来发送第2个指令,然后再返回一个东西,判断再类推.我想知道 我上面的代码是不是只有写一次就够i了 最终到最后我索需要的就是最后那条指令返回的recvStr ?
有可能需要的数据一次Receive后就可以得到,也有可能接收的数据长度不够,这样就需要把数据暂存下,等下次接受后,通过拼包来获取足够的数据。 目前的处理逻辑会导致有的时候正常,有的时候异常。 正确的处理是在这里进行循环,如果接收足够,则跳出循环,继而解析数据, 否则继续接收。

110,534

社区成员

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

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

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