C# Socket

转载地址:https://blog.csdn.net/weixin_49959955/article/details/123798500

using System.Net;
using System.Net.Sockets;
using System.Text;

namespace SocketServer
{ /// <summary>
/// 服务端
/// </summary>
public partial class frmServer : Form
{
//这里声明多个套接字是为了在连接,接收数据,发送数据的函数中不发生混乱,同时方便
public Socket ServerSocket;
public static List<Socket> soketsList = new List<Socket>(); //创建一个全

public static int SFlag = 0; //连接成功标志
public static int CFlag = 0; //客户端关闭的标志

Thread th1; //声明线程1
Thread th2; //声明线程2

public frmServer()
{
InitializeComponent();
}

private void frmServer_Load(object sender, EventArgs e)
{
Control.CheckForIllegalCrossThreadCalls = false;
string IPaddress = "127.0.0.1";
int Post = 8045;
tb_Address.Text = IPaddress;
tb_Post.Text = Post.ToString();
}

#region 连接客户端(绑定按钮事件)
private void btn_Connect_Click(object sender, EventArgs e)
{
ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //创建用
rtb_Recieve.Text += "正在连接...\n";
btn_Connect.Enabled = false; //禁止操作接收按钮

//1.绑定IP和Port
IPAddress IP = IPAddress.Parse(tb_Address.Text);
int Port = int.Parse(tb_Post.Text);

//IPAddress ip = IPAddress.Any;
IPEndPoint iPEndPoint = new IPEndPoint(IP, Port);
try
{
//2 使用Bind()进行绑定
ServerSocket.Bind(iPEndPoint);
//开启监听
ServerSocket.Listen(10);

th1 = new Thread(Listen); //线程绑定listen函数
th1.IsBackground = true; //运行线程在后台执行
th1.Start(ServerSocket); //Start里面的参数是Listen函数需要的参数,这里传送的是用于通信的Socket对象
Console.WriteLine("1");
}
catch (Exception)
{
MessageBox.Show("服务器出问题了");
}
}
#endregion

#region 建立与客户端的连接

void Listen(object sk)
{
try
{
while (true)
{
//GNFlog如果为1就进行中断连接,使用在标志为是为了保证能够顺利关闭服务器端
//当客户端关闭一次后,如果没有这个标志位会使得服务器端一直卡在中断的位置
//如果服务器端一直卡在中断的位置就不能顺利关闭服务器端

//4.阻塞到有client连接
Socket Client = ServerSocket.Accept(); //声明用于与某一个客户端通信的套接字。
soketsList.Add(Client); //将连接的客户端存进List

//获取客户端信息将不同客户端并存进comBox
string client = Client.RemoteEndPoint.ToString();
cb_Clients.Items.Add(client);
cb_Clients.SelectedIndex = 0;

CFlag = 0;//连接成功,将客户端关闭标志设置为0
SFlag = 1;//当连接成功,将连接成功标志设置为1

rtb_Recieve.Text += DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss") + client + "连接成功";
rtb_Recieve.Text += "\r\n";

//开启第二个线程接收客户端数据
th2 = new Thread(Receive); //线程绑定Receive函数
th2.IsBackground = true; //运行线程在后台执行
th2.Start(Client); //Start里面的参数是Listen函数所需要的参数,这里传送的是用于通信的Socket对象
}
}
catch (Exception)
{
}
}
#endregion

#region 接收客户端数据
void Receive(Object sk)
{
Socket socket = sk as Socket; //创建用于通信的套接字(这里是线程传过来的client套接字)
while (true)
{
try
{
if (CFlag == 0 && SFlag == 1)
{
//5。接收数据
byte[] recieve = new byte[1024];
int len = socket.Receive(recieve);

//6.打印接收数据
if (recieve.Length > 0)
{
//如果接收到客户端停止的标志
if (Encoding.UTF8.GetString(recieve, 0, len) == "*close*")
{
rtb_Recieve.Text += DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss ") + "客户端已关闭"+"\n";
CFlag = 1; //将客户端关闭标志设置为1
break; //退出循环
}
//打印接收数据
rtb_Recieve.Text += "*" + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss ");
rtb_Recieve.Text += "接收" + socket.RemoteEndPoint.ToString() + ":";
//rtb_Recieve.Text += Encoding.ASCII.GetString(recieve,0,len); //将字节数据根据
rtb_Recieve.Text += Encoding.UTF8.GetString(recieve, 0, len)+"\n"; //接收中文不会乱码
}
}
else
{
break; //跳出循环
}
}
catch (Exception)
{
MessageBox.Show("收不到信息");
break;
}
}
}
#endregion

#region 向客户端发送数据
private void btn_Send_Click(object sender, EventArgs e)
{
//if (SFlag == 1 && CFlag == 0)
//{
// byte[] send = new byte[1024];
// send = Encoding.UTF8.GetBytes(rtb_Recieve.Text); //将字符串转成字节格式发送

// //打印发送时间和发送的数据
// rtb_Recieve.Text += DateTime.Now.ToString("yy-MM-dd hh:mm:ss ") + "发送:";
// rtb_Recieve.Text += rtb_Recieve.Text + "\n";
// rtb_Recieve.Clear(); //清除发送框
//}

 

//SFlag标志连接成功,同时当客户端是打开的时候才能发送数据
if (SFlag == 1 && CFlag == 0)
{
byte[] send = new byte[1024];
//send = Encoding.ASCII.GetBytes(rtb_Send.Text); //将字符串转成字节格式发送
send = Encoding.UTF8.GetBytes(rtb_Send.Text);

 

//上面将每一个连接的client的套接字信息(ip和端口号)存放进了combox
//我们可以在combox中选择需要通信的客户端
//通过combox_client.SelectedIndex 获取选择的index, 此index对于list中的socket对象
//从而实现对选择的客户端发送信息
int i = cb_Clients.SelectedIndex;
string client = cb_Clients.Text;
soketsList[i].Send(send); //调用Send()向客户端发送数据

//打印发送时间和发送的数据
rtb_Recieve.Text += "*" + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss ") + "向" + client + "发送";
rtb_Recieve.Text += rtb_Send.Text + "\n";
rtb_Send.Clear(); //清除发送框
}
}
#endregion

#region 关闭服务器端
private void btn_Close_Click(object sender, EventArgs e)
{
//若连接上了客户端需要关闭线程2和socket,没连接上客户端直接关闭线程1和其他套接字
if (CFlag == 1)
{
th2.Abort(); //关闭线程2
foreach (Socket s in soketsList)
{
s.Close(); //关闭用于通信的套接字
}
}

ServerSocket.Close(); //关闭用于连接的套接字
//socketAccept.Close(); //关闭与客户端绑定的套接字
th1.Abort(); //关闭线程1

CFlag = 0; //将客户端标志重新设置为0.在进行连接时表示是打开的状态
SFlag = 0; //将连接成功标志程序设置为0,表示退出连接
btn_Accept.Enabled = true;
rtb_Recieve.Text += DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss ");
rtb_Recieve.Text += "服务器已关闭" + "\n";
MessageBox.Show("服务器已关闭");

}
#endregion

#region 点击清除接收款
#endregion

private void btn_Accept_Click(object sender, EventArgs e)
{
rtb_Recieve.Clear();
}
#region 点击enter发送数据
private void rtb_Send_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
this.btn_Send_Click(sender,e); //触发button事件
}
}
#endregion

}
}

 

 

using System.Net;
using System.Net.Sockets;
using System.Text;

namespace SocketClient
{
/// <summary>
/// 客户端
/// </summary>
public partial class frmCllinet : Form
{
public static Socket ClientSocket; //声明负责通信的socket
public static int SFlag = 0; //连接服务器成功标志
Thread th1; //声明一个线程
public frmCllinet()
{
InitializeComponent();
}

private void frmCllinet_Load(object sender, EventArgs e)
{
Control.CheckForIllegalCrossThreadCalls = false;// 执行新线程时跨线程资源访问检查会提示报错,所以这里关闭检测
string IPaddress = "127.0.0.1";
int Post = 8045;
tb_Address.Text = IPaddress;
tb_Post.Text = Post.ToString();
}

#region 连接服务器
private void btn_Connect_Click(object sender, EventArgs e)
{
ClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //声明负责通信的套接字
rtb_Recieve.Text += "正在连接...\n";

IPAddress IP = IPAddress.Parse(tb_Address.Text); //获取设置的IP地址
int Port = int.Parse(tb_Post.Text); //获取设置的端口号
IPEndPoint iPEndPoint = new IPEndPoint(IP, Port); //指定的端口号和服务器的IP建立一个IPEndPoint对象

try
{
ClientSocket.Connect(iPEndPoint); //用Socket对象的Connect()方法以上面建立的IPEndPoint对象作为参数
SFlag = 1; //若连接成功将标志设置为1

rtb_Recieve.Text += DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss ") + tb_Address.Text + "连接成功"+"\n";
btn_Connect.Enabled = false; //禁止操作连接按钮

//开启一个线程接收数据
th1 = new Thread(Receive);
th1.IsBackground = true;
th1.Start(ClientSocket);
}
catch
{
MessageBox.Show("服务器未打开");
}
}
#endregion

#region 接收服务器段数据
void Receive(Object sk)
{
Socket socketRec = sk as Socket;
while (true)
{
//5.接收数据
byte[] receive = new byte[1024];
ClientSocket.Receive(receive); //调用Receive()接收字节数据
//6.打印接收数据
if (receive.Length > 0)
{
rtb_Recieve.Text += "*" + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss ") + "接收:"; //打印接收时间
//rtb_Recieve.Text += Encoding.ASCII.GetString(receive); //将字节数据根据ASCII码转成字符串
rtb_Recieve.Text += Encoding.UTF8.GetString(receive); //使用UTF8编码接收中文不会乱码
rtb_Recieve.Text += "\r\n";
}
}


}
#endregion

#region 向服务器段发送数据
private void btn_Send_Click(object sender, EventArgs e)
{
//只用连接成功了才能发送数据,接收部分因为是连接成功才开启线程,所以不需要使用标志
if (SFlag == 1)
{
byte[] send = new byte[1024];
//send = Encoding.ASCII.GetBytes(rtb_Send.Text); //将文本内容转换成字节发送
send = Encoding.UTF8.GetBytes(rtb_Send.Text); //解决中文乱码问题
ClientSocket.Send(send); //调用Send()函数发送数据

rtb_Recieve.Text += "*" + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss ") + "发送:";
rtb_Recieve.Text += rtb_Send.Text + "\n"; //打印发送的数据
rtb_Send.Clear(); //清空发送
}
}
#endregion

#region 关闭客户端

private void btn_Close_Click(object sender, EventArgs e)
{
//保证是在连接状态下退出
if (SFlag == 1)
{
byte[] send = new byte[1024];
send = Encoding.ASCII.GetBytes("*close*"); //关闭客户端时给服务器发送一个退出标志
ClientSocket.Send(send);

th1.Abort(); //关闭线程
ClientSocket.Close(); //关闭套接字
btn_Connect.Enabled = true; //允许操作按钮
SFlag = 0; //客户段退出后将连接成功标志程序设置为0
rtb_Recieve.Text += DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss ");
rtb_Recieve.Text += "客户端已关闭" + "\n";
MessageBox.Show("已关闭连接");
}
}
#endregion

#region 点击清除接收框
private void btn_Accept_Click(object sender, EventArgs e)
{
rtb_Recieve.Clear();
}
#endregion

/// <summary>
/// 单击Enter发送数据
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void rtb_Send_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
btn_Send_Click(sender,e);
}
}
}
}

 

posted @ 2023-05-19 20:19  KevinSteven  阅读(91)  评论(0编辑  收藏  举报