回 帖 发 新 帖 刷新版面

主题:[求助]C#服务器端与客户端数据传输(使用tcp异步套接字)


我很多不会写的地方在代码中注着。 

其实最头痛的地方简单说就是:服务器如何判断客户端的不同请求,做出相应的处理。 

还有1.是不是我们日常用的都是:服务器数据的发送都是基于客户端的请求。 

2.客户端和服务器都定义了一个   StateObject类, 
public   class   StateObject 
        { 
                public   Socket   workSocket   =   null;   //客户套接字 
                public   const   int   BufferSize   =   1024;   //缓冲区大小 
                public   byte[]   buffer   =   new   byte[BufferSize];   //缓冲区 
        } 
那么这个StateObject类所创建的对象   state   是不是可以理解为即将接收到的信息开辟一个空间,用来存储将要传递来的信息? 


----------------------------

先将客户端的   登录窗体: 

代码: 

namespace openjjkh
{
    public partial class enter : Form
    {
        public enter()
        {
            InitializeComponent();
        }

        private StateObject state;

        private void enter_Load(object sender, EventArgs e)
        {
            try
            {
                IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
                IPEndPoint remoteEP = new IPEndPoint(ipAddress, 5555);
                Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                clientSocket.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), clientSocket);
            }
            catch (Exception ee)
            {
                Console.WriteLine(ee.ToString());
            }
        }
        private void button1_Click(object sender, EventArgs e)
        {
            //传输多个textBox里的信息,Send()方法是不是用多参Send(textBox1.Text,textBox2.Text,1)
            //1 代表服务器端 接受后要采用的相应的处理方法。
            Send(textBox1.Text);
            Send(textBox2.Text);
        }
        private void ConnectCallback(IAsyncResult ar)
        {
            try
            {
                Socket clientSocket = (Socket)ar.AsyncState;
                clientSocket.EndConnect(ar);
                state = new StateObject();
                state.workSocket = clientSocket;
                clientSocket.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }
        public void ReadCallback(IAsyncResult ar)
        {
            StateObject state = (StateObject)ar.AsyncState;
            Socket clientSocket = state.workSocket;
            int bytesRead = clientSocket.EndReceive(ar);
            if (bytesRead = 1)  //这里是当信息被传送回来
            {
                khwindow khzct = new khwindow();
                khzct.Show();
                this.Hide();
            }
            else
            {
                MessageBox.Show("用户名或密码输入错误!!!");
                textBox1.Text = "";
                textBox2.Text = "";
            }
            clientSocket.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
        }
        private void Send(string data)
        {
            /*是否要给Send()在加个参数n,用来传递发送的是哪一类数据,服务器接收后根据这个参数执行相应的处理方法
              比如现在是Send(string date,int n)
             * 但传递的是 用户名和密码...我是不是要写成Send(string date1,string date2,int n)
             * 这样下面就是:
             * byte[] byteData1 = Encoding.Unicode.GetBytes(data1);
               state.workSocket.BeginSend(byteData1, 0, byteData1.Length, 0, new AsyncCallback(SendCallback), state);
             * byte[] byteData2 = Encoding.Unicode.GetBytes(data2);
               state.workSocket.BeginSend(byteData2, 0, byteData2.Length, 0, new AsyncCallback(SendCallback), state);
             * byte[] byteData3 = Encoding.Unicode.GetBytes(n);
               state.workSocket.BeginSend(n, 0, n.Length, 0, new AsyncCallback(SendCallback), state);
             * 这样写行不行,是不是太麻烦了,要是要同时发送10几个textBox里的数据启不是要写10几个参数吗,能不能写到一起啊?
             */
            byte[] byteData = Encoding.Unicode.GetBytes(data);
            state.workSocket.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), state);
        }
        private void SendCallback(IAsyncResult ar)
        {
            try
            {
                Socket clientSocket = (Socket)ar.AsyncState;
                int bytesSent = clientSocket.EndSend(ar);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }

        private void label4_Click(object sender, EventArgs e)
        {
            /*此处点击这个label是弹出个新窗体,让客户端用户进行注册,
             此时新窗体打开后,是否还需要进行连接?
             * 假如在入口函数中采用判断,比如服务器发送来用户的用户名和密码被验证正确,登录了主窗体(而不是注册弹出的窗体),登录窗体Close(),
             * 那在主窗体中是否要重新在进行连接?如果登录窗体时Hide(),是不是就不用了? 
             */
        }

    }
    public class StateObject
    {
        public Socket workSocket = null;
        public const int BufferSize = 1024;
        public byte[] buffer = new byte[BufferSize];
    }
}

在服务器端   主窗体: 

代码: 

namespace openjjsys
{
    public partial class fwzwindow : Form
    {
        public fwzwindow()
        {
            InitializeComponent();
        }

        private  StateObject state;

        private void fwzwindow_Load(object sender, EventArgs e)
        {
            System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;

            IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
            IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 5555);
            Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            try
            {
                serverSocket.Bind(localEndPoint);
                serverSocket.Listen(100);
                serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), serverSocket);
            }
            catch (Exception ee)
            {
                Console.WriteLine(ee.ToString());
            }
        }
        public void AcceptCallback(IAsyncResult ar)
        {
            Socket serverSocket = (Socket)ar.AsyncState;
            Socket clientSocket = serverSocket.EndAccept(ar);
            state = new StateObject();
            state.workSocket = clientSocket;
            clientSocket.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
        }
        private void Send(string data)
        {
            byte[] byteData = Encoding.Unicode.GetBytes(data);
            state.workSocket.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), state);
        }
        private void SendCallback(IAsyncResult ar)
        {
            try
            {
                Socket clientSocket = (Socket)ar.AsyncState;
                int bytesSent = clientSocket.EndSend(ar);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }
        public void ReadCallback(IAsyncResult ar)
        {
            StateObject state = (StateObject)ar.AsyncState;
            Socket clientSocket = state.workSocket;
            int bytesRead = clientSocket.EndReceive(ar);
            
            /*这里需要判断 用户发送来的信息是哪一类的。
             * 比如当bytesRead=1的时候表示:客户端上用户点击了登录,发送的是用户名和密码,此刻要执行查询数据库,返回验证结果。
               如果当bytesRead=2时表示:客户端上用户点击注册,发送了个人的相关信息,服务器要将这些数据添加到数据库,返回注册结果。
               当bytesRead=3时表示:用户以进入客户端主程序后点击一个button,弹出一个新窗体,发送的是要在新窗体的dataGirdView控件中显示他个人信息的请求,
             * 服务器查询数据库,将相应的信息发回去...
             * bytesRead=4 ......等等.......
             * 
             * 在这里是不是这么写?而且clientSocket.EndReceive(ar)最终接收的应该是一组数据信息,它应该把这些信息分开。这里有点晕...  还有那些处理方法写在不同的函数体里调用, 还是把整个放在一个类里?
             * 
             */

            clientSocket.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
        }

        private void fwzwindow_FormClosing(object sender, FormClosingEventArgs e)
        {
            try
            {
                state.workSocket.Shutdown(SocketShutdown.Both);
                state.workSocket.Close();
            }
            catch (Exception) { }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            
        }
    }
    public class StateObject
    {
        public Socket workSocket = null;
        public const int BufferSize = 1024;
        public byte[] buffer = new byte[BufferSize];
    }
}


回复列表 (共6个回复)

沙发

其实也不麻烦
你的思路已经有了,紧密按照这个思路来走就可以了

只不过回调的时候要注意节奏,一环扣一环不要托扣就可以了

板凳

怎么几千字都发不了啊....

3 楼

用NetStream的时候缓存小些,一次发上几十个字节就可以了

4 楼

汗...我是说论坛经常发帖 没到1万字就说超过1万字了...发几千个字都不行...

5 楼

实在没办法,我只能将原帖修改了...

6 楼

大家多提示提示啊....

我来回复

您尚未登录,请登录后再回复。点此登录或注册