【原创】C# Socket网络通信 基础代码 请求品鉴
话不多说 直接上图服务端:
客户端:
客户端服务端执行文件(exe)
服务端关键代码
using System;using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using MyFunc;
namespace _10_13_Socket网络通信
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
//获取本机ip
txtIp.Text = "192.168.1.53";
txtPoint.Text = "50000";
//忽略线程检查
Control.CheckForIllegalCrossThreadCalls = false;
}
Thread th;
IPEndPoint point;
private void BtnListen_Click(object sender, EventArgs e)
{
try
{
//创建侦听socket 采用Tcp stream流 IPV4协议
Socket sktListen = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//获取ip和端口号
point = new IPEndPoint(IPAddress.Parse(txtIp.Text), Convert.ToInt32(txtPoint.Text));
sktListen.Bind(point);//绑定通信信息(ip 和端口号)
sktListen.Listen(10);//设置访问队列
//由于侦听函数Accept()是一直在循环 如果用主进程调用此函数 程序会卡死 因此要创建新线程
th = new Thread(Listen);
th.IsBackground = true;
th.Start(sktListen);
Control.CheckForIllegalCrossThreadCalls = false;
}
catch
{
}
}
public void Listen(object o)
{
try
{
Socket newsktListen = o as Socket;//监听
Socket socketLink;//监听数据
newsktListen.Listen(10);
while (true)//用死循环来无限等待客户端连接
{
socketLink = newsktListen.Accept();//无限循环 直到接收到为止
//Accept结束 必定有客户端进入 这时就要给下拉框以及集合里添加数据了
GetReomtePoint(socketLink.RemoteEndPoint, socketLink);
txtMsg.AppendText(socketLink.RemoteEndPoint.ToString() + "链接成功\r\n");
Thread thMsg = new Thread(GetByte);
thMsg.Start(socketLink);
}
}
catch (Exception)
{
throw;
}
}
//客户连接成功之后 再创建一个线程来不断接收通讯信息
public void GetByte(Object socketLink)
{
try
{
Socket newsocketLink = socketLink as Socket;
//这个时候已经有客户端连接上了 写一个方法用来给下拉框赋值
string str = "";
while (true)
{
byte[] buffer = new byte;
int r = newsocketLink.Receive(buffer);
str = newsocketLink.RemoteEndPoint.ToString() + "Say:" + System.Text.Encoding.Default.GetString(buffer, 0, r);
if (r == 0)
{
break;
}
txtMsg.AppendText(str + "\r\n");
}
}
catch (Exception)
{
throw;
}
}
Dictionary<string, Socket> infodic = new Dictionary<string, Socket>();
int i = 0;
/// <summary>
/// 这个方法是给下拉框赋值 因为后期也要选择客户信息 跟选定的IP通信 因此要用集合记录下来ip 和跟ip通信的socket
/// </summary>
/// <param name="point"></param>
/// <param name="newsocketLink"></param>
public void GetReomtePoint(EndPoint point, Socket newsocketLink)
{
infodic.Add(point.ToString(), newsocketLink);
cmbIPEndPoint.Items.Add(point);
cmbIPEndPoint.SelectedIndex = i;
i++;
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
}
private void BtnSend_Click(object sender, EventArgs e)
{
try
{
//插入0表示发送文本
//发送txtsendmsg中的txt 并给字节数组的第一个索引插入0
byte []bytedata = System.Text.Encoding.Default.GetBytes(txtSendMsg.Text);
bytedata = MyFunc.ByteOperate.Insert(bytedata, 0, 0);
Send(bytedata,txtSendMsg.Text);
}
catch (Exception)
{
throw;
}
//根据key寻找value
}
//写一个发送的方法
public void Send(byte []buffer,string txt)
{
Socket newsocketLink = infodic;
newsocketLink.Send(buffer);
txtMsg.AppendText("Say:" + txt + "\r\n");
//点击之后txtbox中的文本要清空
txtSendMsg.Text = "";
}
OpenFileDialog ofd;
private void BtnSendFile_Click(object sender, EventArgs e)
{
ofd = new OpenFileDialog();
ofd.InitialDirectory = @"F:\PKX桌面";
ofd.Title = "请选择要发送的文件";
ofd.Filter = "图片文件|*.jpg|文本文件|*.txt|音乐文件|*.wav|视频文件|*.rmvb|所有文件|*.*";
ofd.ShowDialog();
string path = ofd.FileName;
if (path=="")
{
return;
}
else
{
using (FileStream fsRead = new FileStream(path, FileMode.Open, FileAccess.Read))
{
byte[] buffer = new byte;
fsRead.Read(buffer, 0, buffer.Length);
buffer = MyFunc.ByteOperate.Insert(buffer, 1, 0);//插入1 表示发送文件
//发送文件
Send(buffer, "发送文件:" + path);
}
}
}
private void BtnShake_Click(object sender, EventArgs e)
{
byte[] buffer = new byte;
buffer = MyFunc.ByteOperate.Insert(buffer, 2, 0);//字节用2表示
Send(buffer,"给对方发送震动");
}
private void btnClose_Click(object sender, EventArgs e)
{
Process.GetCurrentProcess().Kill();
}
}
}
客户端关键代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using MyFunc;
namespace _10_14_Socket网络通信_客户端
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Socket socClient;
private void Form1_Load(object sender, EventArgs e)
{
Control.CheckForIllegalCrossThreadCalls = false;
socClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
}
private void BtnSend_Click(object sender, EventArgs e)
{
try
{
socClient.Send(System.Text.Encoding.Default.GetBytes(txtSend.Text));
txtMsg.AppendText("Say:" + txtSend.Text + "\r\n");
txtSend.Text = "";
}
catch (Exception)
{
throw;
}
}
public void GetByte()
{
try
{
IPAddress ip = IPAddress.Parse("192.168.1.53"); //new IPAddress(System.Text.Encoding.Default.GetBytes("192.168.1.53"));
socClient.Connect(ip,50000);
button1.Hide();
string str = "";
while (true)//这里一定要死循环 循环接收 不能用socClient.Available != 0
{
byte[] buffer = new byte;
int r = socClient.Receive(buffer);
//判断收到的字节的第一个下标的值
switch (buffer)
{
case 0://是文本
{
buffer = MyFunc.ByteOperate.Remove(buffer, 0);
str = socClient.RemoteEndPoint.ToString() + "Say:" + System.Text.Encoding.Default.GetString(buffer, 0, r);
if (r == 0)
{
break;
}
txtMsg.AppendText(str + "\r\n");
}
break;
case 1://是文件
{
buffer = MyFunc.ByteOperate.Remove(buffer, 0);//移除协议
//接收到文件 需要打开保存窗口
SaveFileDialog sfd = new SaveFileDialog();
sfd.Title = "请选择要保存的文件路径和文件名称";
sfd.InitialDirectory = @"F:\PKX桌面";
sfd.ShowDialog(this);
if (sfd.FileName == "")
{
return;
}
else
{
using (FileStream fsWrite = new FileStream(sfd.FileName, FileMode.OpenOrCreate, FileAccess.Write))
{
fsWrite.Write(buffer, 0, buffer.Length);
}
MessageBox.Show("保存成功!");
}
}
break;
case 2://发送的是震动
{
this.Show();
for (int i = 0; i < 500; i++)
{
//this.Location = new Point(220,300);
//this.Location = new Point(230, 310);
//this.Location.X = this.Location.X + 50;
this.Location = new Point(this.Location.X + 10, this.Location.Y + 10);
this.Location = new Point(this.Location.X - 10, this.Location.Y - 10);
}
}
break;
default:
break;
}
}
}
catch (Exception)
{
throw;
}
}
private void Button1_Click(object sender, EventArgs e)
{
Thread th = new Thread(GetByte);
th.IsBackground = true;
th.Start();
Control.CheckForIllegalCrossThreadCalls = false;
}
private void BtnShake_Click(object sender, EventArgs e)
{
}
private void btnClose_Click(object sender, EventArgs e)
{
Process.GetCurrentProcess().Kill();
}
}
}
对了 命名空间里using MyFunc 主要是引用了我自己写的字节操作的函数
因为如果客户发送图片 文字 或者震动的时候 接收方无法判断 需要在发送前插入一个字节 让接收方来判断接收到的是什么
具体实现代码如下:
public static class ByteOperate
{
/// <summary>
/// 给自己数组插入指定的字节
/// </summary>
/// <param name="oldbyte">原字节数组</param>
/// <param name="insertbyet">要插入的字节</param>
/// <param name="index">要插入的索引</param>
/// <returns></returns>
public static byte[] Insert(byte []oldbyte,byte insertbyet,int index)
{
List<byte> list = new List<byte>();
list = oldbyte.ToList();
list.Insert(index, insertbyet);
return list.ToArray();
}
/// <summary>
/// 移除数组中的某个下标的元素
/// </summary>
/// <param name="oldbyte">元素组</param>
/// <param name="index">要移除的某个下标</param>
/// <returns>移除某个元素后的数组</returns>
public static byte[] Remove(byte[] oldbyte, int index)
{
List<byte> list = new List<byte>();
list = oldbyte.ToList();
list.RemoveAt(index);
return list.ToArray();
}
}
页:
[1]