网络编程-实验2-C与C通信

一、实验要求

具体要求包括:

1,Server支持多客户访问;

2,C与S之间使用TCP连接;

3,C与C之间直接通信(不是通过S传递)。

4,C与C之间直接通信既可以使用TCP,也可以使用UDP。

5,可以使用Socket,也可以使用TcpClient/UdpClient等;

6,实验示意图如下:        


二、实验思路

(1)客户端登陆服务端时,打开客户端的监听并发送客户端的用户名和端口号。

(2)客户端发送信息时,服务端根据客户端的用户名返回端口号。

(3)客户端根据服务端返回的端口号与信息接收方进行tcp通信。

(4)客户端与客户端通信时,不保留连接,仅在需要发送信息时建立连接。

三、应用界面

(1)服务器界面:


(2)客户端界面(未登录):


(3)客户端界面(登陆):

 

(4)客户端与客户端互相通信:

 


 

 

(5)客户端给多个客户端发送消息:

 

(6)客户端退出:

 


源码如下:

ClientForm.cs:

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

namespace Client
{
    public partial class ClientForm : Form
    {
        public ClientForm()
        {
            InitializeComponent();
            UserNameList = new List
   
   
    
    ();
            UserPortList = new List
    
    
     
     ();
            isMessageCome = false;
            this.label_State.Text = "未检测到服务器";
            this.FormClosing += ClientWindow_Closing;
        }
        private bool isMessageCome { get; set; }
        private bool isLogin { get; set; }
        private TcpListener listener;
        private TcpClient SocketForClient;
        private BinaryReader br_C;
        private BinaryWriter bw_C;

        private string receiveString;
        private List
     
     
      
       UserNameList { get; set; }
        private List
      
      
       
        UserPortList { get; set; }
        private TcpClient client_S;
        private NetworkStream networkStream_S;
        private BinaryReader br_S;
        private BinaryWriter bw_S;
        private IPAddress localIpAddress;
        private int remotePort;
        private string remoteHost;
        private string userName { get; set; }
        private string userPort { get; set; }
        private enum clientState
        {
            Login,
            Talk,
            Logout
        };

        private delegate void Delegate1();
        private delegate void Delegate2();

        private void ClientWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            if (client_S != null)
            {
                SendMessageToServer(clientState.Logout, "退出服务器。", textBox_Port.Text);
                br_S.Close();
                bw_S.Close();
                client_S.Close();
            }
        }

        private void ClientLogin()
        {
            GetHostAddress();
            remotePort = 51888;
            remoteHost = Dns.GetHostName();
            try
            {
                client_S = new TcpClient(remoteHost, remotePort);
                this.label_State.Text = "连接服务器成功。";
                NetworkStream networkStream = client_S.GetStream();
                br_S = new BinaryReader(networkStream);
                bw_S = new BinaryWriter(networkStream);
                Thread threadReceive = new Thread(ReceiveDataFromServer);
                threadReceive.IsBackground = true;
                threadReceive.Start();
                UpdateClientForm();

                //打开监听器
                listener = new TcpListener(localIpAddress, Convert.ToInt16(userPort));
                listener.Start();
                Thread thread_for_listener = new Thread(ReceiveClient);
                thread_for_listener.IsBackground = true;
                thread_for_listener.Start();

            }
            catch
            {
                //MessageBox.Show(ex.ToString());
                this.label_State.Text = "服务器尚未启动,连接服务器失败。";
                return;
            }
        }
        //接收客户端与客户端之间的连接
        private void ReceiveClient()
        {
            receiveString = null;
            while (true)
            {
                try
                {
                    //MessageBox.Show("8", DateTime.Now.ToString());
                    SocketForClient = listener.AcceptTcpClient();
                    networkStream_S = SocketForClient.GetStream();
                    bw_C = new BinaryWriter(networkStream_S);
                    br_C = new BinaryReader(networkStream_S);
                    receiveString = br_C.ReadString();
                    //MessageBox.Show(receiveString, this.userName);
                    if (receiveString != null)
                    {
                        Delegate1 d1 = new Delegate1(AddInfo_C);
                        textBox_ReceivedMessage.Invoke(d1);
                    }
                    br_C.Close();
                    bw_C.Close();
                    networkStream_S.Close();
                    SocketForClient.Close();
                }
                catch
                {
                    break;
                }
            }
        }

        //从服务器接收数据
        private void ReceiveDataFromServer()
        {
            receiveString = null;
            while (true)
            {
                try
                {
                    receiveString = br_S.ReadString();
                    //MessageBox.Show("5", DateTime.Now.ToString());
                    if (isUserInfo(receiveString))
                    {
                        //更新在线用户列表
                        this.UserNameList.Clear();
                        string[] s = receiveString.Split(',');
                        for (int i = 0; i < s.Length - 1; i++)
                        {

                            if (s[i] != this.userName)
                            {
                                UserNameList.Add(s[i]);
                            }
                        }
                        Delegate2 d2 = new Delegate2(AddUserToList);
                        this.listBox_UserName.Invoke(d2);
                    }
                    else if (isUserPort(receiveString))
                    {
                        this.UserPortList.Clear();
                        string[] s = receiveString.Split(',');
                        int count = Convert.ToInt32(s[0]);
                        for (int i = 0; i < count; i++)
                        {
                            if (s[i + 1] != this.userPort)
                            {
                                UserPortList.Add(s[i + 1]);
                            }
                        }

                        string message = "";
                        for (int i = count + 1; i < s.Length - 1; i++)
                        {
                            message += s[i];
                        }
                        //MessageBox.Show(message);
                        for (int i = 0; i < UserPortList.Count; i++)
                        {
                            //MessageBox.Show(UserPortList.Count.ToString());
                            SendMessageToClient(UserPortList[i], message);
                        }
                        
                    }
                    else
                    {
                        if (textBox_ReceivedMessage.InvokeRequired)
                        {
                            Delegate1 d1 = new Delegate1(AddInfo_S);
                            textBox_ReceivedMessage.Invoke(d1);
                        }
                    }
                }
                catch
                {
                    break;
                }
            }
        }

        //添加信息到面板中
        private void AddInfo_S()
        {
            textBox_ReceivedMessage.Text += DateTime.Now.ToString() + " Server:" + receiveString + "\r\n";
        }
        private void AddInfo_C()
        {
            string[] s = receiveString.Split(',');
            StringBuilder sb = new StringBuilder();
            for (int i = 1; i < s.Length; i++)
            {
                sb.Append(s[i]);
            }
            textBox_ReceivedMessage.Text += DateTime.Now.ToString() + " " + s[0] + ":" + sb.ToString() + "\r\n";
        }
        //添加信息到在线用户面板中
        private void AddUserToList()
        {
            this.listBox_UserName.Items.Clear();
            foreach (string name in UserNameList)
            {
                this.listBox_UserName.Items.Add(name);
            }
        }

        //判断是否是用户信息
        private bool isUserInfo(string receiveString)
        {
            string[] s = receiveString.Split(',');
            if (s[s.Length - 1] == "@UserName")
            {
                return true;
            }
            return false;
        }
        //判断是否是用户端口号
        private bool isUserPort(string receiveString)
        {
            string[] s = receiveString.Split(',');
            if (s[s.Length - 1] == "@UserPort")
            {
                return true;
            }
            return false;
        }

        //发送状态和信息
        //重载1,启动状态和离开状态
        private void SendMessageToServer(clientState state, string message, string port)
        {
            try
            {
                if (message != "" && port != "")
                {
                    switch (state)
                    {
                        case clientState.Login:
                            bw_S.Write("Login," + textBox_UserName.Text + "," + port);
                            break;
                        case clientState.Logout:
                            bw_S.Write("Logout," + message);
                            break;
                        default:
                            break;
                    }
                    bw_S.Flush();

                }

            }
            catch { return; }
        }
        //重载2,交流状态
        private void SendMessageToServer(clientState state, List
       
       
         list, string message) { try { if (clientState.Talk == state && list.Count > 0 && message != "") { //MessageBox.Show("2", DateTime.Now.ToString()); bw_S.Write("Talk," + GetUserNameFromListBox(list) + message); bw_S.Flush(); } } catch { return; } } //获取需要列表中选中的用户名 private string GetUserNameFromListBox(List 
        
          list) { string names = ""; int i = list.Count; names = i.ToString() + ","; foreach (string name in list) { names += name + ","; } return names; } public void UpdateClientForm() { this.textBox_IPAddress.Text = localIpAddress.ToString(); this.userName = textBox_UserName.Text; this.userPort = textBox_Port.Text; } private void GetHostAddress() { IPAddress[] ips = Dns.GetHostAddresses(Dns.GetHostName()); foreach (var v in ips) { if (v.AddressFamily == AddressFamily.InterNetwork) { localIpAddress = v; break; } } } //判断信息传送对象 private List 
         
           GetListBoxSelectedItems(ListBox listBox_UserName) { List 
          
            list = new List 
           
             (); for (int i = 0; i < listBox_UserName.SelectedItems.Count; i++) { list.Add(listBox_UserName.SelectedItems[i].ToString()); } return list; } private void btn_SendMessage_Click(object sender, EventArgs e) { if (isLogin) { //MessageBox.Show("1", DateTime.Now.ToString()); SendMessageToServer(clientState.Talk, GetListBoxSelectedItems(this.listBox_UserName), this.textBox_SendMessage.Text); textBox_SendMessage.Clear(); } } //根据端口号发送信息 private void SendMessageToClient(string userPort, string message) { try { //MessageBox.Show("7", DateTime.Now.ToString()); TcpClient c = new TcpClient(remoteHost, Convert.ToInt32(userPort)); NetworkStream networkStream = c.GetStream(); BinaryWriter bw = new BinaryWriter(networkStream); BinaryReader br = new BinaryReader(networkStream); bw.Write(this.userName + "," + message); bw.Flush(); bw.Close(); br.Close(); networkStream.Close(); c.Close(); //MessageBox.Show("关闭流"); } catch { MessageBox.Show("error 01"); } } private void btn_Login_Click(object sender, EventArgs e) { if (textBox_UserName.Text != "" && textBox_Port.Text != "") { ClientLogin(); SendMessageToServer(clientState.Login, userName, userPort); textBox_UserName.Enabled = false; textBox_Port.Enabled = false; btn_Login.Enabled = false; isLogin = true; } } private void ClientForm_Load(object sender, EventArgs e) { } } } 
            
           
          
         
       
      
      
     
     
    
    
   
   

ServerForm.cs :

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

namespace Server
{

    public partial class ServerForm : Form
    {

        //Variables6
        public static IPAddress localIpAddress;
        public static int port = 51888;
        private TcpListener myListener;
        private TcpClient SocketForClient;
        private NetworkStream networkStream;
        private Thread myThread;
        private string message;
        private delegate void delegate1();
        private delegate void delegate_AddInfo();

        //Attributes

        //Functions
        public ServerForm()
        {
            InitializeComponent();
            this.Closing += ThreadServer_Closing;
            try
            {
                GetHostAddress();
                UpdateServerForm();
                OpenTcpListener();
                OpenOtherListener();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
                MessageBox.Show("服务器初始化失败", "提示");
            }

        }

        //后台检测需不需要更新面板
        private void UpdateInfoListener()
        {
            while (true)
            {
                while (CC.updated == true)
                {
                    delegate1 d = new delegate1(UpdateClientList);
                    this.dataGridView1.Invoke(d);
                    CC.updated = false;
                }
            }
        }

        //后台检测功能
        private void OpenOtherListener()
        {
            Thread messageListener = new Thread(MessageListener);
            messageListener.IsBackground = true;
            messageListener.Start();
            Thread updateInfoListener = new Thread(UpdateInfoListener);
            updateInfoListener.IsBackground = true;
            updateInfoListener.Start();
        }

        //后台检测是否有信息需要输出到message面板中
        private void MessageListener()
        {
            while (true)
            {
                while (CC.messageQueue.Count > 0)
                {
                    message = CC.messageQueue.Dequeue();
                    delegate_AddInfo delegate1 = new delegate_AddInfo(AddInfo);
                    textBox_ReceivedMessage.Invoke(delegate1);
                }
            }
        }
        private void AddInfo()
        {
            this.textBox_ReceivedMessage.Text += message + "\r\n";
        }

        //获取本机地址
        private void GetHostAddress()
        {
            IPAddress[] ips = Dns.GetHostAddresses(Dns.GetHostName());
            foreach (var v in ips)
            {
                if (v.AddressFamily == AddressFamily.InterNetwork)
                {
                    localIpAddress = v;
                    break;
                }
            }
        }

        //更新服务器面板部分信息
        public void UpdateServerForm()
        {
            this.textBox_IPAddress.Text = localIpAddress.ToString();
            this.textBox_Port.Text = port.ToString();
        }

        //开启tcp监听器
        private void OpenTcpListener()
        {
            try
            {
                myListener = new TcpListener(localIpAddress, port);
                myListener.Start();
                label_State.Text = string.Format("开始在{0}:{1}监听客户连接", localIpAddress, port);
                myThread = new Thread(ListenClientConnection);
                myThread.IsBackground = true;
                myThread.Start();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
                label_State.Text = "服务器启动监听失败,请尝试重新启动。";
            }
        }

        //tcp监听器
        private void ListenClientConnection()
        {
            while (true)
            {
                try
                {
                    SocketForClient = myListener.AcceptTcpClient();
                    networkStream = SocketForClient.GetStream();
                    User user = new User(SocketForClient);
                    CC.userList.Add(user);
                    user.ReceiveData();
                    delegate1 d = new delegate1(UpdateClientList);
                    this.dataGridView1.Invoke(d);
                    CC.SendToClient(user, "Hello!");
                }
                catch
                {
                    break;
                }
            }
        }

        //客户端关闭的时候
        private void ThreadServer_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            if (myListener != null)
            {
                if (SocketForClient != null)
                {
                    SocketForClient.Close();
                    networkStream.Close();
                }
                myListener.Stop();
                this.label_State.Text = "服务器已关闭";
            }
        }

        //添加在线用户到数组中
        private void AddClientToCC()
        {
            CC.Count = 0;
            foreach (DataGridViewRow dr in this.dataGridView1.Rows)
            {
                CC.Count++;
            }
            CC.Count--;
            int i = 0;
            foreach (DataGridViewRow dr in this.dataGridView1.Rows)
            {
                if (i < CC.Count)
                {
                    CC.userNamePort[i, 0] = dr.Cells[0].Value.ToString();
                    CC.userNamePort[i, 1] = dr.Cells[1].Value.ToString();
                    i++;
                }
            }
        }

        //更新客户端列表
        private void UpdateClientList()
        {
            if (CC.userList.Count > 0)
            {
                try
                {
                    this.dataGridView1.Rows.Clear();
                    System.Threading.Thread.Sleep(1000);
                    //创建表的行,并与表相关联。
                    foreach (User user in CC.userList)
                    {
                        DataGridViewRow dr = new DataGridViewRow();
                        dr.CreateCells(dataGridView1);
                        dr.Cells[0].Value = user.UserName;
                        dr.Cells[1].Value = user.UserPort;
                        this.dataGridView1.Rows.Add(dr);
                    }
                    AddClientToCC();
                    //发送消息给所有客户端以更新用户列表信息
                    CC.UpdateClientList(CC.userList);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }
            }
            else
            {
                this.dataGridView1.Rows.Clear();
            }
        }

        //发送消息的按钮事件
        private void btn_SendMessage_Click(object sender, EventArgs e)
        {
            if (this.textBox_SendMessage.Text != "")
            {
                string sendMessage = this.textBox_SendMessage.Text;
                List
   
   
    
     selectedUser = new List
    
    
     
     ();
                foreach (User user in CC.userList)
                {
                    //遍历选中的行对象
                    foreach (DataGridViewRow dr in this.dataGridView1.SelectedRows)
                    {
                        //判断是否存在于user列表中
                        if (dr.Cells[0].Value.ToString() == user.UserName && dr.Cells[1].Value.ToString() == user.UserPort)
                        {
                            selectedUser.Add(user);
                            break;
                        }
                    }
                }
                CC.SendToClient(selectedUser, sendMessage);
                this.textBox_SendMessage.Text = "";
            }
        }
        //创建客户端
        private void btn_CreateClient_Click(object sender, EventArgs e)
        {
            ClientForm cForm = new ClientForm();
            cForm.Show();
        }

        private void ServerForm_Load(object sender, EventArgs e)
        {

        }

        private void btn_Flush_Click(object sender, EventArgs e)
        {
            UpdateClientList();
        }
    }
}

    
    
   
   

CC.cs:

using System;
using System.Collections.Generic;
using System.Windows.Forms;

namespace Server
{
    public class CC
    {
        public static List
   
   
    
     userList { get; set; }
        public static Queue
    
    
     
      messageQueue { get; set; }
        public static Dictionary
     
     
      
       Users { get; set; }
        public static bool updated { get; set; }
        public static string[,] userNamePort { get; set; }
        public static int Count { get; set; }
        static CC()
        {
            userList = new List
      
      
       
       ();
            userNamePort = new string[100,2];
            messageQueue = new Queue
       
       
         (); Users = new Dictionary 
        
          (); } public static void SendToServer(string message) { messageQueue.Enqueue(message); } public static void RemoveUser(User user) { userList.Remove(user); } public static void SendToClient(List 
         
           selectedUser, string message) { foreach (User user in selectedUser) { user.bw.Write(message); user.bw.Flush(); } } public static void SendToClient(User selectedUser, string message) { //MessageBox.Show("4", DateTime.Now.ToString()); selectedUser.bw.Write(message); selectedUser.bw.Flush(); } //更新用户信息列表 public static void UpdateClientList(List 
          
            selectedUser) { string info = ""; foreach (User user in selectedUser) { info += user.UserName + ","; } info += "@UserName"; foreach (User user in selectedUser) { user.bw.Write(info); user.bw.Flush(); } } internal static void SendToClient(string message) { throw new NotImplementedException(); } } } 
           
          
         
       
      
      
     
     
    
    
   
   

User.cs:
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows.Forms;
namespace Server
{
    public class User
    {
        public BinaryReader br { get; private set; }
        public BinaryWriter bw { get; private set; }
        public string receiveString { get; set; }
        public bool isRead { get; set; }
        private TcpClient client;
        private NetworkStream networkStream;
        private Thread IOThread;
        private delegate void delegateAddInfo();
        private string mmessage;
        public string UserName;
        public string UserPort;

        public User(TcpClient client)
        {
            this.client = client;
            networkStream = client.GetStream();
            br = new BinaryReader(this.networkStream);
            bw = new BinaryWriter(this.networkStream);
        }

        public void ReceiveData()
        {
            IOThread = new Thread(ReceiveFromClient);
            IOThread.Start();
        }
        //接收信息
        private void ReceiveFromClient()
        {
            while (true)
            {
                receiveString = null;
                try
                {
                    receiveString = br.ReadString();
                }
                catch
                {
                    CC.RemoveUser(this);
                    return;
                }
                string[] split = receiveString.Split(',');
                switch (split[0])
                {
                    case "Login":
                        UserName = split[1];
                        UserPort = split[split.Length - 1];
                        mmessage = DateTime.Now.ToString() + " " + UserName + "[" + UserPort + "]" + "成功连接服务器。";
                        break;
                    case "Talk":
                        mmessage = DateTime.Now.ToString() + " " + UserName + "[" + UserPort + "]" + GetMessage(receiveString);
                        break;
                    case "Logout":
                        mmessage = DateTime.Now.ToString() + " " + UserName + "[" + UserPort + "]" + "已与服务器断开。";
                        //删除并更新面板

                        CC.RemoveUser(this);
                        CC.updated = true;
                        CC.UpdateClientList(CC.userList);
                        break;
                    default:
                        break;
                }
                CC.SendToServer(mmessage);
            }
        }
        //处理信息中的用户信息,查看转发对象。
        private List
    
    
     
      SendMessageToWho(string receiveString)
        {
            List
     
     
      
       users = new List
      
      
       
       ();
            string[] s = receiveString.Split(',');
            try
            {
                int number = Convert.ToInt32(s[1]);
                if (number > 0)
                {

                    for (int i = 0, j = 2; i < number; i++, j++)
                    {
                        users.Add(s[j]);
                    }
                }
                return users;
            }
            catch { return null; }
        }
        //处理信息
        private string GetMessage(string receviceString)
        {
            //MessageBox.Show("3", DateTime.Now.ToString());
            string[] s = receviceString.Split(',');
            StringBuilder sb = new StringBuilder();
            StringBuilder sb_Return = new StringBuilder();
            List
       
       
        
         list = SendMessageToWho(receiveString);
            sb.Append("向");
            sb_Return.Append(list.Count.ToString() + ",");
            for (int i = 0; i < list.Count; i++)
            {
                sb.Append(list[i] + ",");
                sb_Return.Append(GetUserPort(list[i]) + ",");
            }
            sb.Append("发送了消息:");
            for (int i = list.Count + 2; i < s.Length; i++)
            {
                sb.Append(s[i]);
                sb_Return.Append(s[i]);
            }
            sb_Return.Append(",@UserPort");
            CC.SendToClient(this,sb_Return.ToString());
            return sb.ToString();
        }

        private string GetUserPort(string UserName)
        {
            for(int i = 0;i
        
        
       
       
      
      
     
     
    
    




 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值