C#网络通信问题

wbj_ake 2012-11-21 12:10:33
商定协议如下:
客户端发送单个字符'p’,服务器接收到'p'后,将'p'返回给客户端,然后客户端发送4个字节的参数码给
服务器,服务器接收到参数后返回字符'b',客户端发送结束字符'f'给服务器,服务器接收到'f',回发字
符'f'给客户端,通信结束;

现在出现问题是:服务器三次回发给客户端的字符'p','b','f',但客户端接收到得字符出错了,却是三个'p'。

客户端网络实现代码如下:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Net;
using System.Net.Sockets;
using System.Threading;
using Network.DataStruct;


namespace Network {
class TcpClient {
private Socket _Socket = null;
private IPEndPoint ipEndPoint = null;

public string retMsg = null; //接收回传数据
public byte[] buffer = new byte[4]; //发送与接收的缓冲区
/*
* 构造函数
*/
public TcpClient(IPContext _ipContext) {
InitSocket(_ipContext.ip, _ipContext.port);
}

public TcpClient(IPAddress _ip,int _port) {
InitSocket(_ip, _port);
}

/*
* 初始化Socket
*/
private void InitSocket(IPAddress _ip, int _port) {
ipEndPoint = new IPEndPoint(_ip, _port);
_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_Socket.SendTimeout = 2000;
_Socket.ReceiveTimeout = 3000;
_Socket.ReceiveBufferSize = 1;
}
/*
* 连接初始化后的_Socket
* 连接成功返回true
* 连接失败返回false
*/
public bool TcpConnect(){
try {
_Socket.Connect(ipEndPoint);
} catch(SocketException se) {
Console.WriteLine(" SocketException : {0}", se.ToString());
return false;
} catch (Exception e) {
Console.WriteLine(e.ToString());
return false;
}

return true;
}

/*
* 发送msg字符串到_Socket连接的端点
*
*/
public bool TcpSend(string msg) {
do {
try {
if (_Socket.Poll(50, SelectMode.SelectWrite)) {
/*
*检测网络是否能够被写(即能否发送)
*正确直行Send函数
*不正确程序睡眠100ms,继续检测
*该函数陷入不会死循环
*/
int bytesSent = _Socket.Send(Encoding.ASCII.GetBytes(msg));
Console.WriteLine(" TcpSend --> Send Message : {0}", msg.ToString());
if (bytesSent > 0) break;
}
} catch (Exception e) {
Console.WriteLine(" TcpSend --> Network connection is break ,{0}",e.ToString());
return false;
}
Thread.Sleep(100);
} while (true);
return true;
}

public bool TcpSend(byte[] msg) {
do {
try {
if (_Socket.Poll(50, SelectMode.SelectWrite)) {
/*
*检测网络是否能够被写(即能否发送)
*正确直行Send函数
*不正确程序睡眠100ms,继续检测
*该函数陷入不会死循环
*/
int bytesSent = _Socket.Send(msg);
for(int i = 0;i < msg.Length;i ++)
Console.WriteLine(" TcpSend --> Send Message : "+ msg[i]);
if (bytesSent > 0) break;
}
} catch (Exception e) {
Console.WriteLine(" TcpSend --> Network connection is break ,{0}", e.ToString());
return false;
}
Thread.Sleep(100);
} while (true);
return true;
}

public bool TcpSend(byte _msg) {
byte[] msg = new byte[1];
msg[0] = _msg;
do {
try {
if (_Socket.Poll(50, SelectMode.SelectWrite)) {
/*
*检测网络是否能够被写(即能否发送)
*正确直行Send函数
*不正确程序睡眠100ms,继续检测
*该函数陷入不会死循环
*/
int bytesSent = _Socket.Send(msg);
for (int i = 0; i < msg.Length; i++)
Console.WriteLine(" TcpSend --> Send Message : " + msg[i]);
if (bytesSent > 0) break;
}
} catch (Exception e) {
Console.WriteLine(" TcpSend --> Network connection is break ,{0}", e.ToString());
return false;
}
Thread.Sleep(100);
} while (true);
return true;
}

/*
* 从已经初始化完成的_Socket中,获取已接收到得字符串
*/
public bool TcpReceive() {
int TimeOut = 0;
do {
Thread.Sleep(100);
try {
if (_Socket.Poll(50, SelectMode.SelectRead)) {
/*
*检测网络是否能够被写(即能否发送)
*正确直行Send函数
*不正确程序睡眠100ms,继续检测
*该函数陷入死循环可能性极小,情况如下:
*在100ms内,信号机回传了
*/
int bytesRecv = _Socket.Receive(buffer);
if (bytesRecv > 0) {
retMsg = Encoding.ASCII.GetString(buffer);
dtLog.Log(" TcpReceive --> Recv Message :" + (_Socket.RemoteEndPoint as IPEndPoint).Address.ToString() + buffer[0] +" len : "+ bytesRecv.ToString());
break;
}
}
} catch (Exception e) {
Console.WriteLine(" TcpReceive --> Network connection is break ,{0}",e.ToString());
return false;
}
if (++TimeOut >= 19) return false; //超时设置2秒
} while (true);
return true;
}

public bool TcpEnd() {
try {
_Socket.Shutdown(SocketShutdown.Both);
_Socket.Close();
}catch(Exception e){
Console.WriteLine(" TcpEnd --> Network connection is break ,{0}",e.ToString());
return false;
}
return true;
}

public bool TcpTestConnect() {
return _Socket.Connected;
}

}
}

逻辑代码:

private void ParameterCommand(TcpClient _TcpClient, IPContext _ipContext) {
byte[] data = { 0x0D, 0x0B, 0x1B, 0x0B, 0x02, 0x23};
//string data = "141127110235";
int i = 0;
_TcpClient.TcpConnect();

_TcpClient.TcpSend("p");
_TcpClient.TcpReceive();
if (_TcpClient.buffer[0].Equals(0x70)) { //接收到返回的‘p’
_TcpClient.buffer[0] = 0xff;
_TcpClient.TcpSend(data);
_TcpClient.TcpReceive();
if (_TcpClient.buffer[0].Equals(0x62)) { //接收到返回的‘b’
Console.WriteLine("buf[1] : " + _TcpClient.buffer[2]);
_TcpClient.buffer[0] = 0xff;
_TcpClient.TcpSend("f");
_TcpClient.TcpReceive();
if (_TcpClient.buffer[0].Equals(0x66)) { //接收到返回的‘f’
Console.WriteLine("buf[2] : " + _TcpClient.buffer[3]);
Console.WriteLine("通信结束:" + _TcpClient.buffer[0]);
//return;
}
} else {
Console.WriteLine("没有等待返回的'b',返回值为:" + _TcpClient.buffer[0]);
}
} else {
Console.WriteLine("没有等待返回的'p',返回值为:" + _TcpClient.buffer[0]);
}

}


我猜测是不是TCP的缓冲区没有改变,一直保存的是第一次接收的字符'p'!!

求各位给点建议啊!谢谢
...全文
390 13 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
ksq2010 2012-11-22
  • 打赏
  • 举报
回复
引用 10 楼 wbj_ake 的回复:
引用 5 楼 ksq2010 的回复:每次客户端接收的完之后,记得立即清空缓存。 _TcpClient.TcpSend("p"); _TcpClient.TcpReceive(); if (_TcpClient.buffer[0].Equals(0x70)) { //接收到返回的‘p’ ……
接收的缓存,还有就是,你这里的接收最好采用异步接收。。。。。
wbj_ake 2012-11-22
  • 打赏
  • 举报
回复
引用 5 楼 ksq2010 的回复:
每次客户端接收的完之后,记得立即清空缓存。 _TcpClient.TcpSend("p"); _TcpClient.TcpReceive(); if (_TcpClient.buffer[0].Equals(0x70)) { //接收到返回的‘p’ _TcpClient.buffer[0] = 0xff; ……
请问清空缓存,缓存是指自己定义的接收缓存还是系统定义Socket的接收缓存?
wbj_ake 2012-11-22
  • 打赏
  • 举报
回复
但是现在出现了该问题留下的后遗症,能很快接收'p',但是接收结束'b'和接收字符'f'的时候,速度非常慢啊 要接收400次左右才能收到字符'b',‘f’,求解释啊!!!?
痴才 2012-11-22
  • 打赏
  • 举报
回复
好深奥啊
  • 打赏
  • 举报
回复
帮楼主顶起,对C#的网络通信很感兴趣
wbj_ake 2012-11-22
  • 打赏
  • 举报
回复
问题解决了,因为服务器的数据没有到达,客户端就去接收了。因为协议的各个步骤我只是去send 与recv都只有一次,所以读取得都是原来的值,将程序改成如下:

private void ParameterCommand(TcpClient _TcpClient, IPContext _ipContext) {
            byte[] data = { 0x0D, 0x0B, 0x1B, 0x0B, 0x02, 0x23};
            //string data = "141127110235";
            int step = 0;
            //int i = 0;
            _TcpClient.TcpConnect();

            do {
                if (step == 0) { //发送 p 命令
                    _TcpClient.TcpSend("p");
                    _TcpClient.TcpReceive();
                    if (_TcpClient.buffer[0].Equals(0x70)) step++;
                } else if (step == 1) { //发送数据
                    _TcpClient.TcpSend(data);
                    _TcpClient.TcpReceive();
                    if (_TcpClient.buffer[0].Equals(0x62)) step++;
                } else if (step == 2) { //发送结束字符
                    _TcpClient.TcpSend("f");
                    _TcpClient.TcpReceive();
                    if (_TcpClient.buffer[0].Equals(0x66)) break;
                } 
                Thread.Sleep(1000);
            } while (true);
            
        }
ksq2010 2012-11-22
  • 打赏
  • 举报
回复
每次客户端接收的完之后,记得立即清空缓存。 _TcpClient.TcpSend("p"); _TcpClient.TcpReceive(); if (_TcpClient.buffer[0].Equals(0x70)) { //接收到返回的‘p’ _TcpClient.buffer[0] = 0xff; _TcpClient.TcpSend(data); //这里写清空缓存 _TcpClient.TcpReceive(); if (_TcpClient.buffer[0].Equals(0x62)) { //接收到返回的‘b’ Console.WriteLine("buf[1] : " + _TcpClient.buffer[2]); _TcpClient.buffer[0] = 0xff; _TcpClient.TcpSend("f"); //这里写清空缓存 _TcpClient.TcpReceive(); if (_TcpClient.buffer[0].Equals(0x66)) { //接收到返回的‘f’ Console.WriteLine("buf[2] : " + _TcpClient.buffer[3]); Console.WriteLine("通信结束:" + _TcpClient.buffer[0]); //这里写清空缓存 //return;
wbj_ake 2012-11-22
  • 打赏
  • 举报
回复
有可能是这个原因啊,我客户端的自己定义的缓冲区已经清空了,而且重新复制为0xff,但是接受到的值还是一直都是‘p’,猜测原因是:TCP socket的缓冲区中一直是‘p’,怎么清空socket的缓冲区啊?
wbj_ake 2012-11-22
  • 打赏
  • 举报
回复
问题解决了,接分吧
wbj_ake 2012-11-22
  • 打赏
  • 举报
回复
也想过用异步传输啊
chiasing 2012-11-21
  • 打赏
  • 举报
回复
是不是你客户端接受p后保存起来了,然后在让接受,赋值就行赋不上值了啊!!
wbj_ake 2012-11-21
  • 打赏
  • 举报
回复
有没有人帮看一下啊,在线等啊。。。
wbj_ake 2012-11-21
  • 打赏
  • 举报
回复
自己顶一下啊

111,098

社区成员

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

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

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