C# Socket 如何完全发送/接收数据

例子:有两个按钮B1和B2。B1:一个100次的循环,连续发送1~100的数字。即每次循环Send一次。B2:发送一个0问题:按下B1后,接收端大概只接收前10个左右的数... 例子:
有两个按钮B1和B2。
B1:一个100次的循环,连续发送1~100的数字。即每次循环Send一次。
B2:发送一个0

问题:
按下B1后,接收端大概只接收前10个左右的数字(接收端创建新线程,死循环接收数据)。这时按下B2发送一个0,接到的大约是10~20之间的数字,每次接收的数字个数不等。不再次发送就收不到新的数据。这样数据就越堆越多了。
我不确定是发送时没有发完,还是接收时没有接完(应该不是没接完吧,都死循环接收数据的)。

所以我想知道,如何让它一次发完所有数据。
展开
 我来答
大野瘦子
高粉答主

推荐于2019-09-03 · 繁杂信息太多,你要学会辨别
知道小有建树答主
回答量:1227
采纳率:100%
帮助的人:34.6万
展开全部

发送:

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
展开全部

比如B1:1-100是一个“数据包”,B2:0是一个“数据包”,每次发送以“数据包”为单位发送,“数据包”中包含“开始”和“结束”的标记,那么 发送端 B1,B2的执行可以想象成 数据包B1:B1开始+1~100+B1结束,数据包B2:B2开始+0+B2结束,接受端 接受到数据包B1的"B1开始"标记时,创建B1线程,B1线程接受到1~10时,接受端 接受到数据包B2的"B2开始"标记,创建B2线程,B2线程接受0,B2线程接受"B2结束"标记,释放B2线程,同时B1线程接受到11~100和"B1结束"标记释放B1线程。

文字描述的不是很给力,图片例子看看,希望能让你明白。

                                                

追问
不,结果不是这样的,虽然,一开始只接到了1~10左右,但是按下B2按钮,并不是会接到0,而是继续接11~20,再按B2,接到21~30,再按B2,接到31~40,以此类推,到最后的时候才会一下子接到很多个0。
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
xiangjuan314
推荐于2017-10-13 · TA获得超过3.3万个赞
知道大有可为答主
回答量:2.9万
采纳率:0%
帮助的人:2912万
展开全部

服务器端:

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();
        }
    }
}
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
天涯3039847
2014-08-21 · 超过61用户采纳过TA的回答
知道答主
回答量:122
采纳率:0%
帮助的人:146万
展开全部
你在发送端 设置一个标志,说明我发送的东西已经发送完毕,你接受的时候,判断接受的网络流中是否有这个标志,如果有,代表已经接收完整了。否则没有。
打字不易,如满意,望采纳。
追问
没有接收完毕,但也没有继续发送,只有在下一次调用Send时候,接收端才会收到之后的一部分。
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
shuibiyy
推荐于2017-09-29 · TA获得超过1724个赞
知道小有建树答主
回答量:446
采纳率:100%
帮助的人:144万
展开全部
存在情况:
1、 接收端循环没写好

2、没有读完网络流(缓存可以设大些,或判断是否读到完所有的字节)

建议
要一次发完所有数据 可以先将100个数字拼接成字符串,然后发送一次 。字符串头可加入[length=XXX]其中xxx是实际发送的字符串长度(注意不是字节数组buffer的长度),那么对于上面的请求,则我们发送的数据为:“[length=9]1,2,23,54”。而服务端接收字符串之后,首先读取这个“元数据”的内容,然后再根据“元数据”内容来读取实际的数据。取得内空后就可以拆分成数字
更多追问追答
追问


这个是我接收数据的代码,在接不到数据的时候,代码会停在

int iRead = SOCKET.ReceiveFrom(byRead, ref ENDPOINT);

这段代码上。

追答
方法贴出来
本回答被提问者采纳
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
收起 更多回答(3)
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式