C#建立TCP/IP连接
在C/S模式下做网络信号传输,使用TCP/IP协议是首选。
其传输机制:
首先服务端与客户端建立套接字(socket)连接,建立完套接字后,服务端与客户端通过套接字进行数据传输。通常服务端和客户端需要各开启一个线程进行数据的接收。
1.构建连接
首先服务端开启套接字监听服务,然后客户端根据服务器的IP、端口进行连接。
1.1服务端开启套接字
Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream,ProtocolType.Tcp);
serverSocket.Bind(new IPEndPoint(ip, myProt)); //绑定IP地址:端口
serverSocket.Listen(10);//设定最多10个排队连接请求
注意在绑定IP时serverSocket.Bind(new IPEndPoint(ip, myProt));
如果使用127.0.0.1时,客户端连接服务端的IP也必须是127.0.0.1,即要求服务端、客户端都在本地才可以通联。因此,需要将服务器套接字绑定的IP改为对外的IP,如192.168.0.1;
获取对外IP的方法为
/// <summary>
/// 获取本地IP
/// </summary>
/// <returns></returns>
private string GetAddressIP()
{
string AddressIP = string.Empty;
foreach (IPAddress _IPAddress in Dns.GetHostEntry(Dns.GetHostName()).AddressList)
{
if (_IPAddress.AddressFamily.ToString() == "InterNetwork")
{
AddressIP = _IPAddress.ToString();
}
}
return AddressIP;
}
1.2开启监听客户端连接的线程
new Thread(ListenClientConnect).Start(this);
/// <summary>
/// 监听客户端连接
/// </summary>
private static void ListenClientConnect(object server)
{
Server myServer = (Server)server;
myServer.clientSocket = serverSocket.Accept();//线程在此等待,直到有客户端连接后方继续执行
myServer.clientSocket.Send(Encoding.UTF8.GetBytes("连接成功"));
Thread receiveThread = new Thread(ReceiveMessage);//启动接收信息线程
receiveThread.Start(server);
}
当serverSocket.Accept()执行后就完成了套接字的建立,就可以发送消息了。
1.3客户端建立与服务端的连接
客户端也定义一个套接字 clientSocket,再调用其connect方法与服务端连接。
public bool createConn()
{
try
{
IPAddress ip = IPAddress.Parse(textBox_serverIp.Text);
clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
int connPort = Int16.Parse(textBox_serverPort.Text);
clientSocket.Connect(new IPEndPoint(ip, connPort)); //配置服务器IP与端口
writeLog("连接服务器成功");
button_createConn.Text = "断开连接";
//开启监听线程
receiveThread = new Thread(receiveMsg);
receiveThread.Start(this);
}
catch (Exception e)
{
writeLog("连接服务器失败" + e.ToString());
return false;
}
return true;
}
2.数据传输
2.1数据发送
服务端与客户端数据发送均是调用Socket进行传输。注意传输的数据需要进行编码Encoding.UTF8.GetBytes()
/// <summary>
/// 发送消息
/// </summary>
/// <param name="signal"></param>
/// <returns></returns>
private bool sendSignal(string signal)
{
if (clientSocket == null)
{
writeLog("发送失败,未连接客户端");
return false;
}
try
{
clientSocket.Send(Encoding.UTF8.GetBytes(signal + "。"));
return true;
}
catch (Exception e)
{
writeLog("发送失败" + e.ToString());
clientSocket = null;
}
return false;
}
2.2数据接收
数据的接收建议开启一个新的线程进行接收,接收是通过调用socket的Receive方法实现的。
new Thread(receiveMsg).Start(this);
/// <summary>
/// 接受消息处理线程
/// </summary>
/// <param name="clientForm"></param>
public static void receiveMsg(object clientForm)
{
Client myClient = (Client)clientForm;
byte[] result = new byte[1024];
while (true)
{
try
{
//通过clientSocket接收数据
int receiveLength = myClient.clientSocket.Receive(result);
string resultStr = Encoding.UTF8.GetString(result, 0, receiveLength);
myClient.writeLog(string.Format("接收服务器消息:{0}", resultStr));
}
catch (Exception e)
{
myClient.writeLog("读取数据失败,服务器可能已经断开" + e.ToString());
Thread.Sleep(300);
myClient.closeConn();
}
}
}
3.关闭连接
想套接字发送关闭的信号后,将本地套接字关闭
clientSocket.Shutdown(SocketShutdown.Both);
myServer.clientSocket.Close();