第一次做CS的程序,关于socket的,通过各种资料的搜索,其实我觉得说白了主要就分为:
1、套结的关键字。
2、服务器和客户机的远程通信。
3、消息的处理。
服务器原理:
1 //把ip地址转换为实例 2 IPAddress ipa = IPAddress.Parse("127.0.0.1"); 3 //监听端口8001 4 TcpListener mylsn = new TcpListener(ipa, 8001); 5 //开启监听 6 mylsn.Start(); 7 //输出监听成功的信息 8 Console.WriteLine("在8001启动服务,等待连接"); 9 //等待处理接入连接请求10 while (true)11 {12 Socket mysock = mylsn.AcceptSocket();13 Console.WriteLine("有连接,连接来自" + mysock.RemoteEndPoint);14 work w = new work();15 w.mysock = mysock;16 w.mylsn = mylsn;17 Thread t = new Thread(new ThreadStart(w.main));18 t.Start();19 }
class类:
1 class work 2 { 3 public Socket mysock; 4 public TcpListener mylsn; 5 public void main() 6 { 7 //接收客户端消息 8 byte[] data = new byte[100]; 9 mysock.Receive(data);10 string rt = System.Text.UTF8Encoding.UTF8.GetString(data);11 Console.WriteLine(rt);12 //给客户端发消息13 mysock.Send(UTF8Encoding.UTF8.GetBytes("server callback"));14 //释放资源15 mysock.Close();16 mylsn.Stop();17 }18 }
客户机原理:
1 int port = 8001; 2 string host = "127.0.0.1"; 3 //创建终结点EndPoint 4 IPAddress ip = IPAddress.Parse(host); 5 IPEndPoint ipe = new IPEndPoint(ip, port); //把ip和端口转化为IPEndPoint的实例 6 7 //创建Socket并连接到服务器 8 Socket c = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // 创建Socket 9 Console.WriteLine("Connecting...");10 c.Connect(ipe); //连接到服务器11 12 //向服务器发送信息13 string sendStr = "Hello,this is a socket test";14 byte[] bs = Encoding.ASCII.GetBytes(sendStr); //把字符串编码为字节15 16 Console.WriteLine("Send message");17 c.Send(bs, bs.Length, 0); //发送信息18 19 //接受从服务器返回的信息20 string recvStr = "";21 byte[] recvBytes = new byte[1024];22 int bytes;23 bytes = c.Receive(recvBytes, recvBytes.Length, 0); //从服务器端接受返回信息24 recvStr += Encoding.ASCII.GetString(recvBytes, 0, bytes);25 Console.WriteLine("client get message:{0}", recvStr); //回显服务器的返回信息26 27 Console.ReadLine();28 //一定记着用完Socket后要关闭29 c.Close();
命名空间:System.Net和System.Net.Sockets(通信) System.IO(消息字节处理)
到这里,我想通信已经完整的建立了,但是有些小朋友肯定会问,这只是一个简单的客户机和主机的联系,那么,一个主机,N个客户机,又是怎么回事呢,
服务器原理:
1 private TcpListener myListener; 2 myListener = new TcpListener(localAddress, port); 3 myListener.Start(); 4 5 service.AddItem(string.Format("开始在{0}:{1}监听客户端连接", localAddress, port)); 6 //创建一个线程监听客户端连接请求 7 ThreadStart ts = new ThreadStart(ListenClientConnect);//委托 8 Thread myThread = new Thread(ts); 9 myThread.Start();10 11 12 private void ListenClientConnect()13 {14 while (true)15 {16 TcpClient newClient = null;17 try18 {19 //等待用户进入20 newClient = myListener.AcceptTcpClient();21 }22 catch23 {24 //当单击“停止监听”或者退出此窗体时AcceptTcpClient()会产生异常25 //因此可以利用此异常退出循环26 break;27 }28 //每接受一个客户端连接,就创建一个对应的线程循环接收客户端发来的信息29 ParameterizedThreadStart pts = new ParameterizedThreadStart(ReceiveData);//委托30 Thread threadReceive = new Thread(pts);31 User user = new User(newClient);32 threadReceive.Start(user);33 userList.Add(user);34 service.AddItem(string.Format("{0}进入", newClient.Client.RemoteEndPoint));35 service.AddItem(string.Format("当前连接用户数:{0}", userList.Count));36 }37 }38 39 private void ReceiveData(object obj)40 {41 User user = (User)obj;42 TcpClient client = user.client;43 //是否正常退出接收线程44 bool normalExit = false;45 //用于控制是否退出循环46 bool exitWhile = false;47 while (exitWhile == false)48 {49 //当前要传送的数据50 string receiveString = null;51 try52 {53 receiveString = user.sr.ReadLine();54 }55 catch (Exception ex)56 {57 //该客户底层套接字不存在时会出现异常58 service.AddItem("接收数据失败,原因:" + ex.Message);59 }60 //TcpClient 对象将套接字进行了封装,如果TcpClient对象关闭了,61 //但是底层套接字未关闭,并不产生异常,但是读取的结果为 null62 if (receiveString == null)63 {64 if (normalExit == false)65 {66 //如果停止了监听,Connected 为 false67 if (client.Connected == true)68 {69 service.AddItem(string.Format("与{0}失去联系,已停止接收该用户信息",70 client.Client.RemoteEndPoint));71 }72 }73 //退出循环74 break;75 }76 service.AddItem(string.Format("来自{0}:{1}", user.userName, receiveString));77 string[] splitString = receiveString.Split(',');78 string command = splitString[0].ToLower();79 //获取当前传送的数据80 switch (command)81 {82 default:83 service.SendToAll(userList, "要发送的数据");84 break;85 }86 }87 userList.Remove(user);88 client.Close();89 service.AddItem(string.Format("有一个退出,剩余连接用户数:{0}", userList.Count));90 }
Service类:
class Service { private ListBox listbox; private delegate void AddItemDelegate(string str); private AddItemDelegate addItemDelegate; public Service(ListBox listbox) { this.listbox = listbox; addItemDelegate = new AddItemDelegate(AddItem); } ////// 在listbox中追加信息 /// /// 要追加的信息 public void AddItem(string str) { if (listbox.InvokeRequired) listbox.Invoke(addItemDelegate, str); else { listbox.Items.Add(str); listbox.SelectedIndex = listbox.Items.Count - 1; listbox.ClearSelected(); } } ////// 向某个客户端发送信息 /// /// 指定客户 /// 信息 public void SendToOne(User user, string str) { try { user.sw.WriteLine(str); user.sw.Flush(); AddItem(string.Format("向{0}发送{1}", user.userName, str)); } catch (Exception ex) { AddItem(string.Format("向{0}发送消息失败,原因:{1}", user.userName, ex.Message)); } } ////// 向所有客户端发送信息 /// /// 客户列表 /// 信息 public void SendToAll(ListuserList, string str) { for (int i = 0; i < userList.Count; i++) { SendToOne(userList[i], str); } } }
客户机组(list)类:
1 ///2 /// 客户机 3 /// 4 class User 5 { 6 public TcpClient client { get; set; } 7 public StreamReader sr { get; private set; } 8 public StreamWriter sw { get; private set; } 9 public string userName { get; set; }10 public User(TcpClient client)11 {12 this.client = client;13 this.userName = "";14 NetworkStream netStream = client.GetStream();15 sr = new StreamReader(netStream, Encoding.UTF8);16 sw = new StreamWriter(netStream, Encoding.UTF8);17 }18 }
其实,现在呢,就是把整个客户机放到一个list里面,而listbox只是为了单纯的显示消息而已
客户机原理:
1 private TcpClient client = null; 2 private StreamWriter sw; 3 private StreamReader sr; 4 private Service service; 5 //是否正常退出接收线程 6 private bool normalExit = false; 7 8 ///9 /// 连接服务器10 /// 11 private void GetService()12 {13 try14 {15 client = new TcpClient();16 //服务器IP17 client.Connect(IPAddress.Parse(ConfigurationManager.AppSettings["IP"]), int.Parse(ConfigurationManager.AppSettings["Port"]));18 //获取网络流19 NetworkStream netStream = client.GetStream();20 sr = new StreamReader(netStream, System.Text.Encoding.UTF8);21 sw = new StreamWriter(netStream, System.Text.Encoding.UTF8);22 //信息基本提示23 service = new Service(listBox1, sw);24 //给服务器消息25 service.SendToServer("success");26 //数据处理(服务器消息)27 Thread threadReceive = new Thread(new ThreadStart(ReceiveData));28 threadReceive.Start();29 }30 catch (Exception ex)31 {32 MessageBox.Show("与服务器连接失败,原因:" + ex.Message, "提示",33 MessageBoxButtons.OK, MessageBoxIcon.Information);34 return;35 }36 37 }38 ///39 /// 接受服务器端的消息40 /// 41 private void ReceiveData()42 {43 bool exitWhile = false;44 while (exitWhile == false)45 {46 string receiveString = null;47 try48 {49 receiveString = sr.ReadLine();50 }51 catch52 {53 service.AddItemToListBox("接收数据失败");54 }55 if (receiveString == null)56 {57 if (normalExit == false)58 {59 MessageBox.Show("与服务器失去联系!");60 }61 //结束线程62 break;63 }64 service.AddItemToListBox("收到:" + receiveString);65 string[] splitString = receiveString.Split(',');66 string command = splitString[0].ToLower();67 switch (command)68 {69 default:70 GetControl(command);//这里的GetControl是一个处理值的方法,71 this.Invalidate();72 break;73 }74 }75 Application.Exit();76 }
客户机Service类:
1 class Service 2 { 3 ListBox listbox; 4 StreamWriter sw; 5 public Service(ListBox listbox, StreamWriter sw) 6 { 7 this.listbox = listbox; 8 this.sw = sw; 9 }10 ///向服务器发送数据 11 public void SendToServer(string str)12 {13 try14 {15 sw.WriteLine(str);16 sw.Flush();17 }18 catch19 {20 AddItemToListBox("发送数据失败");21 }22 }23 delegate void ListBoxDelegate(string str);24 ///在listbox中追加信息< 25 /// 要追加的信息26 public void AddItemToListBox(string str)27 {28 try29 {30 if (listbox.InvokeRequired)31 {32 ListBoxDelegate d = AddItemToListBox;33 listbox.Invoke(d, str);34 }35 else36 {37 listbox.Items.Add(str);38 listbox.SelectedIndex = listbox.Items.Count - 1;39 listbox.ClearSelected();40 }41 }42 catch43 {44 45 }46 }47 }
这就是一个完整的socket了,第一次做,肯定很多没有想到的地方,希望大神及时提出宝贵意见。