加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

在使用Visual C#(Dot Net Framework 4.0)的“套接字编程”中需要

发布时间:2020-12-15 21:51:30 所属栏目:百科 来源:网络整理
导读:最近,我接到了一项任务…… “开发可以安装在办公室或企业的各种Windows机器上的Windows窗体应用程序.只有一台机器(ALPHA机器)就有一个数据库.这个数据库将被其他Beta机器上的应用程序用来访问数据应用程序本身会设法检查它是Alpha还是Beta(包含数据库文件?
最近,我接到了一项任务……

“开发可以安装在办公室或企业的各种Windows机器上的Windows窗体应用程序.只有一台机器(ALPHA机器)就有一个数据库.这个数据库将被其他Beta机器上的应用程序用来访问数据应用程序本身会设法检查它是Alpha还是Beta(包含数据库文件?),因此必须充当服务器或客户端.“

除网络和应用程序间通信要求外,我可以做任何事情.所以,我开始通过互联网学习Socket编程,我已经完成了this link …

我正在研究的想法是……

>让客户端将消息发送到服务器.
>让服务器接受此消息并将此消息放入队列中.
>阅读邮件以获取客户的IP地址及其数据请求.
>在数据库上应用此请求并获取结果.
>将结果转换为字符串.
>将其发送给请求客户端.

我可以设法执行步骤3,4和我被困在1,2和2上. 6.

走向这……

我已经为Server以及在调用时返回套接字的客户端创建了一个函数.我创建了一个单独的函数,因为我喜欢我的代码,干净,整洁,多年后可以理解.

检查下面的代码……

对于服务器……

private Socket GetServerReady()
    {
           IPEndPoint RemoteEP = new IPEndPoint(IPAddress.Any,8000);
            Socket newSock = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
            newSock.Connect(RemoteEP);
            newSock.Listen(10);
            return (newSock);
    }

您会注意到任何地方都没有Accept()方法,这是因为我希望将其称为以下内容以供进一步使用…

Socket CltSock = GetServerReady().Accept();

客户代码是……

private Socket GetClientReady()
    {
        IPEndPoint RemoteEP = new IPEndPoint(IPAddress.Parse(txtBxHost2.Text.Trim()),8000);
        Socket ServerSock = new Socket(AddressFamily.InterNetwork,ProtocolType.Tcp);
        ServerSock.Connect(RemoteEP);
        return (ServerSock);
    }

最后,问题是….

>“在哪里调用我上面写的函数的适当位置?”
>“我应该在Form_Load()事件中调用服务器和客户端函数吗?”
>“我的主要意图的下一步是什么,即上面提到的第1,2和6点?”

我不希望我可以复制完整的代码.只需正确的程序和概念的一些细节就可以了.

我只使用一台PC进行测试.另外,另一个限制是,它将全部在单个应用程序中编码.我不想为客户端编写两个单独的应用程序.服务器.

我希望我能清楚地了解你.

非常感谢.

等待回应.

解决方法

我正在努力完成任务并以某种方式设法获得解决方案.

以下是我的解决方案:

服务器端代码:
(我将此代码放在一个函数中,如果捕获到任何异常,它会循环执行)

private void Looper()
    {
        int i = 0;
        int AttemptCount = 1;
        while (i == 0)
        {
            try
            {
                TcpListener tL = new TcpListener(Network.GetLocalIPAddress(),56009);
                tL.Start(10);
                Socket tS = tL.AcceptSocket();

                if (tS.Connected)
                {
                    NetworkStream nS = new NetworkStream(tS);
                    StreamReader Reader = new StreamReader(nS);

                    Output = Reader.ReadToEnd().Trim();

                    Reader.Close();
                    nS.Close();
                    tS.Close();
                    tL.Stop();

                    //If Done,End Execution
                    i = 1;
                }
                else
                {
                    MessageBox.Show("The connection to the client is broken or failed..!!nnPlease check connection and try again.","Error",MessageBoxButtons.OK,MessageBoxIcon.Error);
                }
            }
            catch (SystemException ex)
            {
                //If Not,Loop Execution Again
                if (MessageBox.Show("Exception: " + ex.Message + "nnAttempt Count: " + AttemptCount + "nnDo you want to terminate the transmission?",MessageBoxButtons.YesNo,MessageBoxIcon.Error) == DialogResult.Yes)
                {
                    i = 1;
                    ResetTimer.Stop();
                }
                else
                {
                    i = 0;
                    AttemptCount++;
                }
            }
        }
    }

调用上面的函数时,服务器等待接受任何传入的套接字.如果由于端口重用或任何事情而在某处出现任何错误,它会自行循环并重置服务器. (因此,我们不必再次手动调用服务器功能.)

一旦服务器接受任何传入套接字,执行就会成功结束.很多时候我们不想在接收成功后继续调用服务器.所以,我不是在按钮“click_event”中调用此函数,而是在计时器Tick_Event中调用它.因此,在服务器端消除了人的需求.

这导致了一个问题.一旦服务器开始等待接受,它就处于阻塞模式.
它挂起同一个线程中的所有进程和控件.所以,我将调用上面的函数移到了BackgroundWorker的“Do_Work”事件中.

检查以下代码:

private void GetServerReady()
    {
        if (!bW.IsBusy)
        {
            bW.RunWorkerAsync();
            txtBxHistory.Text += "rn" + Output;
        }
    }

    private void bW_DoWork(object sender,DoWorkEventArgs e)
    {
        Looper();
    }

    private void ResetTimer_Tick(object sender,EventArgs e)
    {
        GetServerReady();
    }

>“bW”是“BackgroundWorker”.
>“输出”是我在全球定义的变量.

我们需要变量的原因是,

BackgroundWorker有自己的线程来执行放置在其“Do_Work”事件中的代码.因此,BackgroundWorker不能使用应用程序线程中的TextBox来存储接收的输出.对变量执行此操作然后将TextBox的Text属性设置为此变量就可以了.

客户端代码:

private void btnSend_Click(object sender,EventArgs e)
    {
        TcpClient socketForServer;
            try
            {
                socketForServer = new TcpClient(txtBxDestIP.Text.Trim(),56009);
            }
            catch
            {
                MessageBox.Show("Failed to connect to server at " + txtBxDestIP.Text.Trim() + ":999",MessageBoxIcon.Error);
                return;
            }
            NetworkStream networkStream = socketForServer.GetStream();
            StreamWriter streamWriter = new System.IO.StreamWriter(networkStream);
            try
            {
                string InputString;
                InputString = Network.GetLocalIPAddress() + ": " + txtBxData.Text;
                streamWriter.Write(InputString);
                streamWriter.Flush();
                socketForServer.Close();
                txtBxHistory.Text += "rnMe: " + txtBxData.Text.Trim();
                txtBxData.Clear();
            }
            catch
            {
                MessageBox.Show("Exception reading from Server.",MessageBoxIcon.Error);
            }
            streamWriter.Close();
            networkStream.Close();
            socketForServer.Close();
    }

>“txtBxDestIP”是具有目标IP地址为Text的TextBox.
>“txtBxData”是具有要发送的文本的TextBox.

这段代码对我来说完美无瑕.通过上述解决方案,我可以实现从步骤1到6的所有动机(在上面的问题中提到.)

我希望它也有助于其他人.请建议是否有更好,更有效的方法来执行此操作.

谢谢.问候.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读