套接字读/写问题 [英] Socket read/write problem

查看:60
本文介绍了套接字读/写问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

你好,

我已经编写了一个字符服务器和一个聊天客户端应用程序.不过我有一个小问题;

我将所有连接的聊天客户端的名称存储在列表中.当新客户端连接时,他将通过套接字接收列表.通过套接字进行迭代并发送的方法如下所示:

(字符串前面的"1"和"0"用于确定如何处理)

Hello,

I have written a char server and a chat client application. I have a little problem though;

I store the names of all connected chat clients in a list. When a new client connects, he will receive the list through a socket. The method that iterates and sends it over the socket looks like this;

(The ''1'' and ''0'' infront of the string is to determine what to do with it)

public static void getClientList(int i)
        {
            foreach (String client in userList)
            {
                workerSocket[i].Send(Encoding.Unicode.GetBytes("1"+client));
            }
        }



它只是简单地遍历列表并发送名称(字符串).


现在,客户端将接收并阅读它.问题是客户端读取的速度不够快-这意味着有时多个名称会在客户端读取所有缓冲区之前到达缓冲区.



It simply iterates through the list and sends the name (a string).


Now, the client will receive and read it. The problem is the client dosn''t read fast enough -- meaning that sometimes multiple names arrive in the buffer before the client can read them all.

public void receive(IAsyncResult asyn)
        {
            string msg = "";
            int readBytes = 0;
            StateObject state = (StateObject)asyn.AsyncState;
            readBytes = state.getWorkSocket().EndReceive(asyn);
            msg = Encoding.Unicode.GetString(state.getBuffer(), 0, readBytes);  // store the received string
            if (readBytes > 0)
            {
                if (msg[0] == '0')   // metadata: start of string is 0 = MESSAGE
                {
                    msg = msg.Remove(0, 1);
                    this.textbox_display.Text = this.textbox_display.Text + msg;
                    this.textbox_display.SelectionStart = this.textbox_display.TextLength;
                    this.textbox_display.ScrollToCaret();
                    state.getWorkSocket().BeginReceive(state.getBuffer(), 0, state.getBufferSize(), 0, new AsyncCallback(receive), state);
                }
                if (msg[0] == '1')   // metadata: start of string is 1 = client list update
                {
                    msg = msg.Remove(0, 1);
                    this.textbox_connected.Text = msg;
                    this.listbox_users.Items.Add(msg);
                    state.getWorkSocket().BeginReceive(state.getBuffer(), 0, state.getBufferSize(), 0, new AsyncCallback(receive), state);
                }
            }
            else {
                this.textbox_display.Text = this.textbox_display.Text + "*** Received 0 bytes? disconnect!";
            }

        }




我如何让发送方等到接收方在发送新的字符串之前先阅读了发送的字符串?我意识到这很困难,因为发件人将字符串分成数据包,所以这不是一个连贯的发送-我的意思是,毕竟这是一个字节流.




How do I make the sender wait untill the receiver has read the sent string before sending a new one? I realise it might be hard since the sender divides the string into packets, so it''s not a coherent sending -- I mean, it''s a bytestream after all. But surely somehow it must be done?

推荐答案

看看msdn示例 ^ ].

在发送数据期间,他们使用了一个名为EndSend 的委托.
这对您应该有用.

他们还使用ManualResetEvent 事件,指示发送已完成.在收到第一个消息并触发此事件之后,可以发送下一条消息.

希望这两个套接字构造可以帮助解决您的问题.
Have a look at the msdn sample here[^].

They have used a delegate called EndSend during sending of data.
This should be useful to you.

They are also using a ManualResetEvent event indicating that the send is done. The next message can be sent after the first one is received and this event is triggered.

Hopefully, these two socket constructs may help resolve your problem.


再次问好,

我已经看过了,但仍然无法正常工作.这是下面的发送部分;

Hello again,

I''ve looked at this, I still cannot get it to work. Here''s the Sending part below;

//
        // send client list to user i 
        //
        public static void getClientList(int i)
        {
            BinaryFormatter bformatter = new BinaryFormatter();
            MemoryStream mem = new MemoryStream();
            foreach (String client in userList)
            {
                // finalize the PDU and send it
                PimpDU pdu = new PimpDU();
                pdu.setType("name");
                pdu.setFrom(client);
                pdu.setPayload(client);
                bformatter.Serialize(mem, pdu);
                workerSocket[i].BeginSend(mem.GetBuffer(), 0, mem.GetBuffer().Length, SocketFlags.None, new AsyncCallback(getClientListCallback), workerSocket[i]);
                getlistDone.WaitOne();
                // reset memory stream
                mem.Position = 0;
                mem.SetLength(0);

            }
        }
        //
        // finishes the getClientList function
        //
        public static void getClientListCallback(IAsyncResult ar)
        {
            Socket client = (Socket)ar.AsyncState;
            client.EndSend(ar);
            getlistDone.Set();
        }





这是收货;





And here''s the receiving;

//
        // received data from server
        //
        public void receive(IAsyncResult asyn)
        {
            BinaryFormatter bformatter = new BinaryFormatter();
            MemoryStream mem = new MemoryStream();
            int readBytes = 0;   
            StateObject state = (StateObject)asyn.AsyncState;
            readBytes = state.getWorkSocket().EndReceive(asyn);

            mem.Write(state.getBuffer(), 0, readBytes);
            mem.Position = 0;
            PimpDU pdu = (PimpDU)bformatter.Deserialize(mem);
            if (readBytes > 0)
            {
                if (pdu.getType()=="message")   // the PDU contains a MESSAGE
                {
                    this.textbox_display.Text = this.textbox_display.Text + pdu.getFrom() + ": " + pdu.getPayload() + "\r\n";
                    this.textbox_display.SelectionStart = this.textbox_display.TextLength;
                    this.textbox_display.ScrollToCaret();
                    state.getWorkSocket().BeginReceive(state.getBuffer(), 0, state.getBufferSize(), 0, new AsyncCallback(receive), state);
                }
                if (pdu.getType()=="name")   // the PDU contains a name of a new client
                {
                    this.listbox_users.Items.Add(pdu.getFrom());
                    state.getWorkSocket().BeginReceive(state.getBuffer(), 0, state.getBufferSize(), 0, new AsyncCallback(receive), state);
                }
            }
            else {
                this.textbox_display.Text = this.textbox_display.Text + "*** Received 0 bytes?!";
            }
         
        }




我知道很多代码对不起:(虽然我无法使它正常工作.当我使用getClientList函数发送字符串列表时,有些只是消失/无法读取.

1.当我的接收缓冲区获得一个以上的对象(PDU)时,我认为只有一个对象是从缓冲区中检索到的,而另一个则被扔掉了吗?有什么方法可以读取第一个对象,看看缓冲区中是否还有其他东西,如果有,请阅读更多内容?

2.我对ManualResetEvent做错了什么吗?




I know it''s alot of code sorry :( I can''t get it to work though. When I send my list of strings using the getClientList function, some simply dissapear/aren''t read.

1. When my receiving buffer gets more than one object(PDU), I take it only one object is retrieved from the buffer, and the other is thrown away? Is there any way to read the first object, see if there''s more stuff in the buffer, and if so read more?

2. Did I do anything wrong with ManualResetEvent?


这篇关于套接字读/写问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆