C# Socket 如何完全发送/接收数据
有两个按钮B1和B2。
B1:一个100次的循环,连续发送1~100的数字。即每次循环Send一次。
B2:发送一个0
问题:
按下B1后,接收端大概只接收前10个左右的数字(接收端创建新线程,死循环接收数据)。这时按下B2发送一个0,接到的大约是10~20之间的数字,每次接收的数字个数不等。不再次发送就收不到新的数据。这样数据就越堆越多了。
我不确定是发送时没有发完,还是接收时没有接完(应该不是没接完吧,都死循环接收数据的)。
所以我想知道,如何让它一次发完所有数据。 展开
发送:
private void button2_Click(object sender, EventArgs e)
{
if (s.Connected == true)
{
try
{
string abc = textBox3.Text;
s.Send(Encoding.ASCII.GetBytes(abc));
MessageBox.Show("向服务器发送:" + abc);
}
catch
{
MessageBox.Show("发送失败");
}
}
}
接收:
System.Timers.Timer aTimer = new System.Timers.Timer();
byte[] res = new byte[1024];
private void Form1_Load(object sender, EventArgs e)
{
Control.CheckForIllegalCrossThreadCalls = false;
aTimer.Enabled = false;
Thread thread1 = new Thread(TimerMange);
thread1.IsBackground = true;
thread1.Start();
}
void TimerMange()
{
aTimer.Elapsed += new ElapsedEventHandler(socket_rev); //定时事件的方法
aTimer.Interval = 100;
}
private void socket_rev(object sender, EventArgs e)
{
int receiveLength = s.Receive(res, res.Length, SocketFlags.None);
if (receiveLength > 0)
{
textBox4.Text = Encoding.ASCII.GetString(res, 0, receiveLength);
string abc = "HaveReceive";
s.Send(Encoding.ASCII.GetBytes(abc));
}
}
扩展资料:
C#Socket异步通讯学习
思路
1、Socket分为面向连接协议(如TCP)和无连接协议(如UDP)
2、Socket通信分为同步操作模式和异步操作模式,同步模式在建立连接之前/收到消息之前会阻塞当前进程,异步模式不会阻塞当前进程
综合以上两点,考虑到体验,当然是选择异步Socket啦,另外,这里使用的是面向连接的协议,那么实现思路大致如下:
1、创建Socket对象
2、绑定IP和端口
3、侦听连接
4、开始一个异步操作来接收一个接入的连接请求
5、处理接入的请求
6、向客户端发送消息
2014-08-21
不,结果不是这样的,虽然,一开始只接到了1~10左右,但是按下B2按钮,并不是会接到0,而是继续接11~20,再按B2,接到21~30,再按B2,接到31~40,以此类推,到最后的时候才会一下子接到很多个0。
服务器端:
namespace SocketTest
{
class Program
{
public static void SendMessage()
{
Socket socket = serverSocket.Accept();
Console.WriteLine("Connected a client:{0}",socket.RemoteEndPoint);
socket.Send(Encoding.ASCII.GetBytes("welcome to server"));
//Thread thread = new Thread(ReceiveMessage);
// thread.Start();
}
public static void ReceiveMessage(object obj)
{
Socket socket = (Socket)obj;
byte[] data = new byte[1024];
int len = socket.Receive(data);
string dataString = Encoding.ASCII.GetString(data, 0, len);
Console.WriteLine("Receive Data:{0} from {1}", dataString,socket.RemoteEndPoint);
//Thread thread = new Thread(SendMessage);
//thread.Start(socket);
}
static Socket serverSocket;
static void Main(string[] args)
{
//定义接收数据长度变量
int recv;
//定义接收数据的缓存
byte[] data = new byte[1024];
//定义侦听端口
IPEndPoint ipEnd = new IPEndPoint(IPAddress.Any, 5566);
//定义套接字类型
serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//连接
serverSocket.Bind(ipEnd);
//开始侦听
serverSocket.Listen(10);
//控制台输出侦听状态
Console.Write("Waiting for a client");
//Socket client;
while (true)
{
//一旦接受连接,创建一个客户端
Socket client = serverSocket.Accept();
//获取客户端的IP和端口
IPEndPoint ipEndClient = (IPEndPoint)client.RemoteEndPoint;
//输出客户端的IP和端口
Console.WriteLine("Connect with {0} at port {1}", ipEndClient.Address, ipEndClient.Port);
//定义待发送字符
string welcome = "Welcome to my server";
//数据类型转换
data = Encoding.ASCII.GetBytes(welcome);
while (true)
{
try
{
//发送
client.Send(data, data.Length, SocketFlags.None);
//接收数据可以用线程也可以不用
//ReceiveMessage(client);
Thread thread = new Thread(ReceiveMessage);
thread.Start(client);
////对data清零
//data = new byte[1024];
////获取收到的数据的长度
//recv = client.Receive(data);
////如果收到的数据长度为0,则退出
//if (recv == 0)
// break;
////输出接收到的数据
//Console.WriteLine(Encoding.ASCII.GetString(data, 0, recv));
//将接收到的数据再发送出去
// client.Send(data, recv, SocketFlags.None);
}
catch (Exception)
{
client.Close();
serverSocket.Close();
}
}
client.Close();
}
//Console.WriteLine("Disconnect form{0}", ipEndClient.Address);
serverSocket.Close();
}
}
}
客户端:
namespace Client
{
class Program
{
public static void sendMessage(object obj)
{
Socket socket = (Socket)obj;
string input = Console.ReadLine();
byte[] data = Encoding.ASCII.GetBytes(input);
socket.Send(data, data.Length, SocketFlags.None);
//Thread thread = new Thread(new ParameterizedThreadStart(ReceiveMessage));
//thread.Start(socket);
}
public static void ReceiveMessage(object obj)
{
Socket socket = (Socket)obj;
byte[] data = new byte[1024];
int len = socket.Receive(data);
string dataString = Encoding.ASCII.GetString(data, 0, len);
Console.WriteLine("Receive Data:{0} from {1}", dataString, socket.RemoteEndPoint);
//Thread thread = new Thread(new ParameterizedThreadStart(SendMessage));
//thread.Start(socket);
}
static void Main(string[] args)
{
//定义发送数据缓存
byte[] data = new byte[1024];
//定义字符串,用于控制台输出或输入
string input, stringData;
//定义主机的IP及端口
IPAddress ip = IPAddress.Parse("127.0.0.1");
IPEndPoint ipEnd = new IPEndPoint(ip, 5566);
//定义套接字类型
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//尝试连接
try
{
socket.Connect(ipEnd);
}
//异常处理
catch (SocketException e)
{
Console.WriteLine("Fail to connect server");
Console.WriteLine(e.ToString());
return;
}
//定义接收数据的长度
int recv = socket.Receive(data);
//将接收的数据转换成字符串
stringData = Encoding.ASCII.GetString(data, 0, recv);
//控制台输出接收到的数据
Console.WriteLine(stringData);
while(true)
{
//Thread thread = new Thread(sendMessage);
//thread.Start(socket);
//定义从键盘接收到的字符串
input = Console.ReadLine();
if (input == "exit")
{
break;
}
//将从键盘获取的字符串转换成整型数据并存储在数组中
data = Encoding.ASCII.GetBytes(input);
//发送该数组
socket.Send(data, data.Length, SocketFlags.None);
////如果字符串是"exit",退出while循环
//if (input == "exit")
//{
// break;
//}
////对data清零
//data = new byte[1024];
////定义接收到的数据的长度
//recv = socket.Receive(data);
////将接收到的数据转换为字符串
//stringData = Encoding.ASCII.GetString(data, 0, recv);
////控制台输出字符串
//Console.Write(stringData);
////发送收到的数据
//socket.Send(data, recv, 0);
}
Console.WriteLine("disconnect from server");
socket.Shutdown(SocketShutdown.Both);
socket.Close();
}
}
}
打字不易,如满意,望采纳。
没有接收完毕,但也没有继续发送,只有在下一次调用Send时候,接收端才会收到之后的一部分。
1、 接收端循环没写好
2、没有读完网络流(缓存可以设大些,或判断是否读到完所有的字节)
建议
要一次发完所有数据 可以先将100个数字拼接成字符串,然后发送一次 。字符串头可加入[length=XXX]其中xxx是实际发送的字符串长度(注意不是字节数组buffer的长度),那么对于上面的请求,则我们发送的数据为:“[length=9]1,2,23,54”。而服务端接收字符串之后,首先读取这个“元数据”的内容,然后再根据“元数据”内容来读取实际的数据。取得内空后就可以拆分成数字
方法贴出来