C#下如何实现服务器+客户端的聊天程序

 

C#下如何实现服务器+客户端的聊天程序

最近也在接触SOCKET编程,在当今这样一个网络时代,很多技术都以网络为中心在诞生,至少我认为是这样的,而SOCKET套接字接口,在实现网络通讯上处于关键地位,所以不会SOCKET是不行的。

首先,本文主要是针对那些刚接触SOCKET编程的朋友,如果是高手,就可以不看此文啦,可以去陪陪老婆,比如逛街或看电视...

在开始之前,我们需要预习一些基础知识:
什么是SOCKET套接字?
SOCKET通常有那几种数据格式?
线程的概念?
(以上基本知识我就不讲了,网上这方面资料很多的,大家找资料看下吧)

我要介绍的是一个服务器端+客户端的聊天系统,程序比较简单,我先把程序运行的界面给大家看下:


上面是服务器端运行界面;下面把客户端界面贴给大家看下:



功能比较简单,服务器的端口号可以在“系统菜单”里面的参数配置进行修改的。

看了上面的图,下面我们就给大家把代码贴出来:(因为程序比较简单,所以本人就没有去分层啦)

服务器端代码:
  1  using  System;
  2  using  System.Collections.Generic;
  3  using  System.ComponentModel;
  4  using  System.Data;
  5  using  System.Drawing;
  6  using  System.Text;
  7  using  System.Windows.Forms;
  8 
  9  using  System.Net;
 10  using  System.Net.Sockets;
 11  using  System.Threading;
 12  using  System.Xml;
 13 
 14  namespace  Server
 15  {
 16       public  partial  class  ServerMain : Form
 17      {
 18           public  ServerMain()
 19          {
 20              InitializeComponent();
 21          }
 22 
 23           private   void  ServerMain_Load( object  sender, EventArgs e)
 24          {
 25               this .CmdStar.Enabled  =   true ;
 26               this .CmdStop.Enabled  =   false ;
 27          }
 28 
 29           private   void  配置参数ToolStripMenuItem_Click( object  sender, EventArgs e)
 30          {
 31              Set TSet  =   new  Set();
 32              TSet.ShowDialog();
 33          }
 34 
 35           private   void  关于ToolStripMenuItem_Click( object  sender, EventArgs e)
 36          {
 37              About TAbout  =   new  About();
 38              TAbout.Show();
 39          }
 40           ///   <summary>
 41           ///  获得XML文件中的端口号
 42           ///   </summary>
 43           ///   <returns></returns>
 44           private   int  GetPort()
 45          {
 46               try
 47              {
 48                  XmlDocument TDoc  =   new  XmlDocument();
 49                  TDoc.Load( " Settings.xml " );
 50                   string  TPort  =  TDoc.GetElementsByTagName( " ServerPort " )[ 0 ].InnerXml;
 51                   return  Convert.ToInt32(TPort);
 52 
 53              }
 54               catch  {  return   6600 ; } // 默认是6600
 55          }
 56 
 57           // 声明将要用到的类
 58           private  IPEndPoint ServerInfo; // 存放服务器的IP和端口信息
 59           private  Socket ServerSocket; // 服务端运行的SOCKET
 60           private  Thread ServerThread; // 服务端运行的线程
 61           private  Socket[] ClientSocket; // 为客户端建立的SOCKET连接
 62           private   int  ClientNumb; // 存放客户端数量
 63           private   byte [] MsgBuffer; // 存放消息数据
 64 
 65           private   void  CmdStar_Click( object  sender, EventArgs e)
 66          {
 67              ServerSocket  =   new  Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
 68              ServerInfo = new  IPEndPoint(IPAddress.Any, this .GetPort());
 69              ServerSocket.Bind(ServerInfo); // 将SOCKET接口和IP端口绑定
 70              ServerSocket.Listen( 10 ); // 开始监听,并且挂起数为10
 71 
 72              ClientSocket  =   new  Socket[ 65535 ]; // 为客户端提供连接个数
 73              MsgBuffer  =   new   byte [ 65535 ]; // 消息数据大小
 74              ClientNumb  =   0 ; // 数量从0开始统计
 75 
 76              ServerThread  =   new  Thread(RecieveAccept); // 将接受客户端连接的方法委托给线程
 77              ServerThread.Start(); // 线程开始运行
 78 
 79              CheckForIllegalCrossThreadCalls  =   false ; // 不捕获对错误线程的调用
 80 
 81               this .CmdStar.Enabled  =   false ;
 82               this .CmdStop.Enabled  =   true ;
 83               this .StateMsg.Text  =   " 服务正在运行 " + "   运行端口: " + this .GetPort().ToString();
 84               this .ClientList.Items.Add( " 服务于  "   +  DateTime.Now.ToString()  +   "  开始运行. " );
 85          }
 86          
 87           // 接受客户端连接的方法
 88           private   void  RecieveAccept()
 89          {
 90               while  ( true )
 91              {
 92                  ClientSocket[ClientNumb]  =  ServerSocket.Accept();
 93                  ClientSocket[ClientNumb].BeginReceive(MsgBuffer,  0 , MsgBuffer.Length,  0 new  AsyncCallback(RecieveCallBack),ClientSocket[ClientNumb]);
 94                   this .ClientList.Items.Add(ClientSocket[ClientNumb].RemoteEndPoint.ToString() + "  成功连接服务器. " );
 95                  ClientNumb ++ ;
 96              }
 97          }
 98 
 99           // 回发数据给客户端
100           private   void  RecieveCallBack(IAsyncResult AR)
101          {
102               try
103              {
104                  Socket RSocket  =  (Socket)AR.AsyncState;
105                   int  REnd  =  RSocket.EndReceive(AR);
106                   for  ( int  i  =   0 ; i  <  ClientNumb; i ++ )
107                  {
108                       if  (ClientSocket[i].Connected)
109                      {
110                          ClientSocket[i].Send(MsgBuffer,  0 , REnd, 0 );
111                      }
112                      RSocket.BeginReceive(MsgBuffer,  0 , MsgBuffer.Length,  0 new  AsyncCallback(RecieveCallBack), RSocket);
113 
114                  }
115              }
116               catch  { }
117 
118          }
119 
120           private   void  CmdStop_Click( object  sender, EventArgs e)
121          {
122              ServerThread.Abort(); // 线程终止
123              ServerSocket.Close(); // 关闭SOCKET
124 
125               this .CmdStar.Enabled  =   true ;
126               this .CmdStop.Enabled  =   false ;
127               this .StateMsg.Text  =   " 等待运行 " ;
128               this .ClientList.Items.Add( " 服务于  "   +  DateTime.Now.ToString()  +   "  停止运行. " );
129          }
130 
131 
132 
133      }
134  }

客户端代码:

  1  using  System;
  2  using  System.Collections.Generic;
  3  using  System.ComponentModel;
  4  using  System.Data;
  5  using  System.Drawing;
  6  using  System.Text;
  7  using  System.Windows.Forms;
  8 
  9  using  System.Net;
 10  using  System.Net.Sockets;
 11 
 12  namespace  Client
 13  {
 14       public  partial  class  ClientMain : Form
 15      {
 16           public  ClientMain()
 17          {
 18              InitializeComponent();
 19          }
 20 
 21           private  IPEndPoint ServerInfo;
 22           private  Socket ClientSocket;
 23           private  Byte[] MsgBuffer;
 24           private  Byte[] MsgSend;
 25 
 26           private   void  ClientMain_Load( object  sender, EventArgs e)
 27          {
 28               this .CmdSend.Enabled  =   false ;
 29               this .CmdExit.Enabled  =   false ;
 30 
 31              ClientSocket  =   new  Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
 32              MsgBuffer  =   new  Byte[ 65535 ];
 33              MsgSend  =   new  Byte[ 65535 ];
 34              CheckForIllegalCrossThreadCalls  =   false ;
 35 
 36              Random TRand = new  Random();
 37               this .UserName.Text  =   " 用户 "   +  TRand.Next( 10000 ).ToString();
 38          }
 39 
 40           private   void  CmdEnter_Click( object  sender, EventArgs e)
 41          {
 42              ServerInfo  =   new  IPEndPoint(IPAddress.Parse( this .ServerIP.Text), Convert.ToInt32( this .ServerPort.Text));
 43 
 44               try
 45              {
 46                  ClientSocket.Connect(ServerInfo);
 47 
 48                  ClientSocket.Send(Encoding.Unicode.GetBytes( " 用户:  "   +   this .UserName.Text  +   "  进入系统!/n " ));
 49 
 50                  ClientSocket.BeginReceive(MsgBuffer,  0 , MsgBuffer.Length,  0 new  AsyncCallback(ReceiveCallBack),  null );
 51 
 52                   this .SysMsg.Text  +=   " 登录服务器成功!/n " ;
 53                   this .CmdSend.Enabled  =   true ;
 54                   this .CmdEnter.Enabled  =   false ;
 55                   this .CmdExit.Enabled  =   true ;
 56              }
 57               catch
 58              {
 59                  MessageBox.Show( " 登录服务器失败,请确认服务器是否正常工作! " );
 60              }
 61          }
 62 
 63           private   void  ReceiveCallBack(IAsyncResult AR)
 64          {
 65               try
 66              {
 67                   int  REnd  =  ClientSocket.EndReceive(AR);
 68                   this .RecieveMsg.AppendText(Encoding.Unicode.GetString(MsgBuffer,  0 , REnd));
 69                  ClientSocket.BeginReceive(MsgBuffer,  0 , MsgBuffer.Length,  0 new  AsyncCallback(ReceiveCallBack),  null );
 70 
 71              }
 72               catch
 73              {
 74                  MessageBox.Show( " 已经与服务器断开连接! " );
 75                   this .Close();
 76              }
 77 
 78          }
 79 
 80           private   void  CmdSend_Click( object  sender, EventArgs e)
 81          {
 82              MsgSend  =  Encoding.Unicode.GetBytes( this .UserName.Text  +   " 说:/n "   +   this .SendMsg.Text  +   " /n " );
 83               if  (ClientSocket.Connected)
 84              {
 85                  ClientSocket.Send(MsgSend);
 86                   this .SendMsg.Text  =   "" ;
 87              }
 88               else
 89              {
 90                  MessageBox.Show( " 当前与服务器断开连接,无法发送信息! " );
 91              }
 92          }
 93 
 94           private   void  CmdExit_Click( object  sender, EventArgs e)
 95          {
 96               if  (ClientSocket.Connected)
 97              {
 98                  ClientSocket.Send(Encoding.Unicode.GetBytes( this .UserName.Text  +   " 离开了房间!/n " ));
 99                  ClientSocket.Shutdown(SocketShutdown.Both);
100                  ClientSocket.Disconnect( false );
101              }
102              ClientSocket.Close();
103 
104               this .CmdSend.Enabled  =   false ;
105               this .CmdEnter.Enabled  =   true ;
106               this .CmdExit.Enabled  =   false ;
107          }
108 
109           private   void  RecieveMsg_TextChanged( object  sender, EventArgs e)
110          {
111               this .RecieveMsg.ScrollToCaret();
112          }
113 
114           private   void  SendMsg_KeyDown( object  sender, KeyEventArgs e)
115          {
116               if  (e.Control  &&  e.KeyValue  ==   13 )
117              {
118                  e.Handled  =   true ;
119                   this .CmdSend_Click( this null );
120              }
121          }
122 
123 
124 
125 
126      }
127  }
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当然,我可以为您提供一个简单C# TCP聊天服务器端口程序示例。以下是一个基本的实现: ```csharp using System; using System.IO; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; public class TCPServer { private TcpListener listener; private TcpClient client; private StreamReader reader; private StreamWriter writer; private bool isRunning; public TCPServer(int port) { listener = new TcpListener(IPAddress.Any, port); isRunning = false; } public void Start() { listener.Start(); isRunning = true; Console.WriteLine("Server started. Waiting for clients..."); client = listener.AcceptTcpClient(); Console.WriteLine("Client connected."); NetworkStream networkStream = client.GetStream(); reader = new StreamReader(networkStream); writer = new StreamWriter(networkStream); // 启动一个新线程用于接收消息 Thread receiveThread = new Thread(ReceiveMessages); receiveThread.Start(); // 发送消息到客户端 while (isRunning) { string message = Console.ReadLine(); SendMessage(message); } } public void Stop() { isRunning = false; if (reader != null) reader.Close(); if (writer != null) writer.Close(); if (client != null) client.Close(); if (listener != null) listener.Stop(); Console.WriteLine("Server stopped."); } private void ReceiveMessages() { try { while (isRunning) { string message = reader.ReadLine(); Console.WriteLine("Client: " + message); } } catch (IOException ex) { Console.WriteLine("Error reading client message: " + ex.Message); } } private void SendMessage(string message) { writer.WriteLine(message); writer.Flush(); } } public class Program { public static void Main(string[] args) { Console.WriteLine("Enter the port number to start the server:"); int port = Convert.ToInt32(Console.ReadLine()); TCPServer server = new TCPServer(port); server.Start(); Console.WriteLine("Press any key to stop the server..."); Console.ReadKey(); server.Stop(); } } ``` 这是一个简单C# TCP聊天服务器端口程序。它创建一个TCP监听器,并等待客户端连接。一旦有客户端连接,它会启动一个新的线程用于接收客户端发送的消息,并在主线程中发送消息到客户端。 请注意,这只是一个基本的示例,可能需要进行一些改进和错误处理,以适应您的具体需求。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值