经测试,两台工控机之间局域网通信正常,如下图:
通过连接客户端的不同开启各自客户端的服务线程,服务器端选取不同客户端也可以通过该服务线程发送消息给客户端。实现代码如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace server
{
public partial class Form1 : Form
{
public delegate void updata (String arg,int i);
Socket mysocket = null;
Dictionary<String, Socket> mydic = new Dictionary<string, Socket> ();
Dictionary<String, Thread> mythread = new Dictionary<string, Thread> ();
public Form1 ()
{
InitializeComponent ();
}
private void Form1_Load ( object sender, EventArgs e )
{
comboBox1.Items.Add ( "等待连接" );
comboBox1.SelectedIndex = comboBox1.Items.IndexOf ( "等待连接" );
String ipadress = "127.0.0.1";
int prots = 3344;
mysocket = new Socket (AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
IPAddress ipsa = IPAddress.Parse (ipadress);
IPEndPoint ipenp = new IPEndPoint (ipsa,prots);
mysocket.Bind (ipenp);
mysocket.Listen (10);
Thread thread1 = new Thread (new ThreadStart(waitconnet));
thread1.IsBackground = true;
thread1.Start ();
}
public void waitconnet ()
{
updata ipda = new updata (updataui);
while(true){
Socket socketconn = mysocket.Accept ();
mydic.Add (socketconn.RemoteEndPoint.ToString(),socketconn);
Invoke (ipda,socketconn.RemoteEndPoint.ToString(),1);
ParameterizedThreadStart pts = new ParameterizedThreadStart(mesgthread);
Thread threadmes = new Thread (pts);
threadmes.IsBackground = true;
threadmes.Start (socketconn);
mythread.Add (socketconn.RemoteEndPoint.ToString(),threadmes);
}
}
public void mesgthread (object socketpra)
{
updata upd = new updata (updataui);
int ststics = 0;
Socket socketrec = socketpra as Socket;
while(true){
byte[] argmesg = new byte[1024 * 1024];
int length = -1;
try
{
length = socketrec.Receive (argmesg);
String getstr = Encoding.UTF8.GetString (argmesg,0,length);
Invoke (upd,getstr,0);
}
catch(Exception ex)
{
if (ststics==0)
{
mydic.Remove (socketrec.RemoteEndPoint.ToString ());
mythread.Remove (socketrec.RemoteEndPoint.ToString());
Invoke (upd,socketrec.RemoteEndPoint.ToString(),2);
Invoke ( upd, socketrec.RemoteEndPoint.ToString ()+ex.ToString(), 0 );
}
ststics = 1;
}
Thread.Sleep (100);
}
}
public void updataui (String arg,int i)
{
if(i==0){
textBox2.Text += arg;
}
else if (i == 1)
{
comboBox1.Items.Add (arg);
comboBox1.SelectedIndex = comboBox1.Items.IndexOf ( arg );
}
else if (i == 2)
{
comboBox1.Items.Remove (arg);
if (comboBox1.Items.Count < 1)
{
comboBox1.Items.Add ( "等待连接" );
comboBox1.SelectedIndex = comboBox1.Items.IndexOf ( "等待连接" );
}
else
{
String keys = comboBox1.Items[comboBox1.Items.Count-1].ToString ();
comboBox1.SelectedIndex = comboBox1.Items.IndexOf ( keys );
}
// comboBox1.Items.Remove (arg);
// comboBox1.SelectedIndex=1;
}
}
private void button1_Click ( object sender, EventArgs e )
{
byte[] strmes = Encoding.UTF8.GetBytes (textBox1.Text.ToString());
String clent = comboBox1.Text;
mydic[clent].Send (strmes);
textBox2.Text += textBox1.Text;
textBox1.Text = "";
}
}
}
线程与UI之间不能直接操作,需要使用委托来实现,服务器接收到客户端的消息也需要通过注册事件来回调主线程更新UI。
委托与事件在C#里是非常重要的,不然很多效果实现不了,还有线程也很重要!
下面附上源码,编译环境是.net4.5,vs2012中编译通过。
客户端代码:C#Socket套接字使用Tcp协议通信(客户端)
原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/241255.html
