c#中的Winsock服务器/客户端应用程序

时间:2016-05-14 11:38:15

标签: c# client-server winsock

我正在使用winsock Control在C#中创建一个客户端/服务器应用程序。我做了所有的事情,但我坚持从客户端到服务器发送数据的地方。在我的程序服务器中,总是使用ip和端口监听客户端。我将数据从客户端发送到服务器。

1)当单击服务器表单上的“监听”按钮时,它会打开客户端连接的服务器。

2)在客户端表单中,我点击服务器已连接的连接按钮为此消息发送消息(Connect Event:ip),我们很容易知道客户端已连接到服务器。

3)然后我们在发送数据文本框中输入一些数据,然后单击发送按钮将数据发送到服务器并保存在客户端。

以下代码:

服务器

using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Net;
using System.Threading;
using System.Net.Sockets;

namespace Server
{
    public partial class Form1 : Form
    {      
        public Form1()
        {
            InitializeComponent();        
        }
        const string DEFAULT_SERVER = "ip";
        const int DEFAULT_PORT = 120;

        System.Net.Sockets.Socket serverSocket;
        System.Net.Sockets.SocketInformation serverSocketInfo;

        public string Startup()
        {               
            IPHostEntry hostInfo = Dns.GetHostByName(DEFAULT_SERVER);
            IPAddress serverAddr = hostInfo.AddressList[0];
            var serverEndPoint = new IPEndPoint(serverAddr, DEFAULT_PORT);            
            serverSocket = new System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
            serverSocket.Bind(serverEndPoint);

            return serverSocket.LocalEndPoint.ToString();    
        }

        public string Listen()
        {
            int backlog = 0;
            try
            {
                serverSocket.Listen(backlog);
                return "Server listening";
            }
            catch (Exception ex)
            {
                return "Failed to listen" + ex.ToString();
            }
        }
        public string ReceiveData()
        {
            System.Net.Sockets.Socket receiveSocket;

            byte[] buffer = new byte[256];

            receiveSocket = serverSocket.Accept();

            var bytesrecd = receiveSocket.Receive(buffer);

            receiveSocket.Close();

            System.Text.Encoding encoding = System.Text.Encoding.UTF8;

            return encoding.GetString(buffer);
        }           

        private void Listen_Click(object sender, EventArgs e)
        {
            string serverInfo = Startup();
            textBox1.Text = "Server started at:" + serverInfo;

            serverInfo = Listen();
            textBox1.Text = serverInfo;

            //string datatosend = Console.ReadLine();
            //SendData(datatosend);

            serverInfo = ReceiveData();
            textBox1.Text = serverInfo;

            //Console.ReadLine();
        }

        private void winsock_DataArrival(object sender, AxMSWinsockLib.DMSWinsockControlEvents_DataArrivalEvent e)
        {
            ReceiveData();
            Listen();
        }

        private void winsock_ConnectEvent(object sender, EventArgs e)
        {
            Listen();
        }
    }
}

这一切都很完美但是在这里我的问题是我只在同一时间从客户端获取数据到服务器。当我再次从客户端向服务器发送数据时,它无法工作,并给我一些消息,如

  

附加信息:每个套接字地址只有一种用法   (协议/网络地址/端口)通常是允许的

以服务器形式

serverSocket.Bind(serverEndPoint);

请有人帮我解决我的问题。

谢谢。

3 个答案:

答案 0 :(得分:1)

试试这个。它可以帮助你

 delegate void AddTextCallback(string text);

        public Form1()
        {
            InitializeComponent();
        }
        private void ButtonConnected_Click(object sender, EventArgs e)
        {
            ThreadPool.QueueUserWorkItem(new WaitCallback(ServerHandler));
        }

        private void ServerHandler(object state)
        {
            TcpListener _listner = new TcpListener(IPAddress.Parse("12.2.54.658"), 145);

            _listner.Start();

            AddText("Server started - Listening on port 145");

            Socket _sock = _listner.AcceptSocket();

            //AddText("User from IP " + _sock.RemoteEndPoint);

            while (_sock.Connected)
            {
                byte[] _Buffer = new byte[1024];

                int _DataReceived = _sock.Receive(_Buffer);

                if (_DataReceived == 0)
                {
                    break;
                }

                AddText("Message Received...");

                string _Message = Encoding.ASCII.GetString(_Buffer);

                AddText(_Message);
            }

            _sock.Close();
            AddText("Client Disconnected.");

            _listner.Stop();
            AddText("Server Stop.");
        }

        private void AddText(string text)
        {
            if (this.listBox1.InvokeRequired)
            {
                AddTextCallback d = new AddTextCallback(AddText);
                this.Invoke(d, new object[] { text });
            }
            else
            {
                this.listBox1.Items.Add(text);
            }
        }

我上个月也遇到了和你一样的问题,但是我使用stackoverflow中的http://stackoverflow.com/questions/21072100/receive-multiple-different-messages-tcp-listner-c-sharp解决了这个问题。这有助于我很多希望它也有助于解决您的问题。

答案 1 :(得分:0)

我不是100%确定你理解TCP套接字,所以这里就是。

当您使用TCP侦听器套接字时,首先绑定到端口,以便客户端具有要连接的固定的已知点。这将为您的套接字保留端口,直到您通过调用该套接字上的Close()来放弃它。

接下来,您将收听以开始接受您绑定的端口上的客户端的过程。你可以同时做到这一点和第一步,但是你没有,我没有在这里。

接下来,您致电Accept()。这会阻止(暂停执行),直到客户端连接,然后它返回一个专用于与该客户端通信的套接字。如果您想允许其他客户端连接,则必须再次致电Accept()

然后,您可以使用Accept()返回的套接字与客户端进行通信,直到完成为止,此时您将在该套接字上调用Close()

当您完成侦听新连接时,请在侦听器套接字上调用Close()

但是当您按下听音按钮时会发生以下情况:

您正确绑定,开始正确收听,然后在接听电话上调用ReceiveData()阻止,直到收到客户端。然后,您会收到一些数据(虽然这是TCP,因此可能不是整个数据!)然后您立即关闭与客户端的连接。

我认为你得到的错误必须再次按下你的服务器上的监听。因此,这会重新启动整个侦听器套接字,当您第二次绑定到端口时,前一个侦听器仍然绑定到该端口,因此调用失败,因为已经在该端口上分配了某些内容。

解决方案是,您需要保持从Accept()调用返回的套接字打开,直到您完成它为止。让客户端通过在其套接字上调用Shutdown()方法来处理关闭,或者建立一些标记通信结束的约定。

当你尝试连接多个用户时,你也会遇到麻烦,所以在某些时候你要么需要线程或一些异步套接字,但我觉得这不属于这个问题的范围。

答案 2 :(得分:0)

我建议你不要使用AxMSWinsockLib ..看看这里给出的socket示例,它展示了如何创建客户端套接字和服务器套接字 - https://msdn.microsoft.com/en-us/library/kb5kfec7(v=vs.110).aspx和这一个 - https://msdn.microsoft.com/en-us/library/6y0e13d3(v=vs.110).aspx