通过本文主要向大家介绍了c#socket通信实例,c#socket编程实例,c#socket实例,c#socket异步通信实例,c#socket类等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com
本文展示了一个C#的Socket操作类的完整实例,并附带了用法说明,分享给大家供大家参考之用。具体方法如下:
主要功能代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Collections;
using System.Net;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using System.Collections.Specialized;
using System.Threading;
public class DuxSocketClient
{
#region 私有字段
/// <summary>
/// 设置数据缓冲区大小 默认1024
/// </summary>
private static int m_maxpacket = 1024 * 4;
public delegate void SendFileProgress(int progress);
public delegate void ReceiveFileProgress(int progress);
#endregion
#region 服务器侦听
/// <summary>
/// 服务器侦听方法 返回null则说明没有链接上
/// </summary>
/// <returns>返回一个套接字(Socket)</returns>
public static Socket ListenerSocket(TcpListener listener)
{
try
{
Socket socket = listener.AcceptSocket();
return socket;
}
catch
{
return null;
}
}
/// <summary>
/// 服务器侦听方法 返回null则说明没有链接上
/// </summary>
/// <param name="listener"></param>
/// <returns>返回一个网络流</returns>
public static NetworkStream ListenerStream(TcpListener listener)
{
try
{
TcpClient client = listener.AcceptTcpClient();
return client.GetStream();
}
catch
{
return null;
}
}
#endregion
#region 客户端连接
public static Socket ConnectSocket(TcpClient tcpclient, IPEndPoint ipendpoint)
{
try
{
tcpclient.Connect(ipendpoint);
return tcpclient.Client;
}
catch
{
return null;
}
}
public static Socket ConnectSocket(TcpClient tcpclient, IPAddress ipadd, int port)
{
try
{
tcpclient.Connect(ipadd, port);
return tcpclient.Client;
}
catch
{
return null;
}
}
public static NetworkStream ConnectStream(TcpClient tcpclient, IPEndPoint ipendpoint)
{
try
{
tcpclient.Connect(ipendpoint);
return tcpclient.GetStream();
}
catch
{
return null;
}
}
public static NetworkStream ConnectStream(TcpClient tcpclient, IPAddress ipadd, int port)
{
try
{
tcpclient.Connect(ipadd, port);
return tcpclient.GetStream();
}
catch
{
return null;
}
}
#endregion
#region Socket接收数据
/// <summary>
/// 接受固定长度字符串
/// </summary>
/// <param name="socket"></param>
/// <param name="size"></param>
/// <returns></returns>
public static byte[] ReceiveFixData(Socket socket, int size)
{
int offset = 0;
int recv = 0;
int dataleft = size;
byte[] msg = new byte[size];
while (dataleft > 0)
{
recv = socket.Receive(msg, offset, dataleft, 0);
if (recv == 0)
{
break;
}
offset += recv;
dataleft -= recv;
}
return msg;
}
/// <summary>
/// 接收变长字符串
/// 为了处理粘包问题 ,每次发送数据时 包头(数据字节长度) + 正文
/// 这个发送小数据
/// 设置包头的字节为8,不能超过8位数的字节数组
/// </summary>
/// <param name="socket"></param>
/// <returns>byte[]数组</returns>
public static byte[] ReceiveVarData(Socket socket)
{
//每次接受数据时,接收固定长度的包头,包头长度为8
byte[] lengthbyte = ReceiveFixData(socket, 8);
//length得到字符长度 然后加工处理得到数字
int length = GetPacketLength(lengthbyte);
//得到正文
return ReceiveFixData(socket, length);
}
/// <summary>
/// 接收T类对象,反序列化
/// </summary>
/// <typeparam name="T">接收T类对象,T类必须是一个可序列化类</typeparam>
/// <param name="socket"></param>
/// <returns></returns>
public static T ReceiveVarData<T>(Socket socket)
{
//先接收包头长度 固定8个字节
byte[] lengthbyte = ReceiveFixData(socket, 8);
//得到字节长度
int length = GetPacketLength(lengthbyte);
byte[] bytecoll = new byte[m_maxpacket];
IFormatter format = new BinaryFormatter();
MemoryStream stream = new MemoryStream();
int offset = 0; //接收字节个数
int lastdata = length; //还剩下多少没有接收,初始大小等于实际大小
int receivedata = m_maxpacket; //每次接收大小
//循环接收
int mark = 0; //标记几次接收到的数据为0长度
while (true)
{
//剩下的字节数是否小于缓存大小
if (lastdata < m_maxpacket)
{
receivedata = lastdata; //就只接收剩下的字节数
}
int count = socket.Receive(bytecoll,0,receivedata,0);
if (count > 0)
{
stream.Write(bytecoll, 0, count);
offset += count;
lastdata -= count;
mark = 0;
}
else
{
mark++;
if (mark == 10)
{
break;
}
}
if (offset == length)
{
break;
}
}
stream.Seek(0, SeekOrigin.Begin); //必须要这个 或者stream.Position = 0;
T t = (T)format.Deserialize(stream);
stream.Close();
return t;
}
/// <summary>
/// 在预先得到文件的文件名和大小
/// 调用此方法接收文件
/// </summary>
/// <param name="socket"></param>
/// <param name="path">路径必须存在</param>
public static bool ReceiveFile(Socket socket, string path, string filename, long size,ReceiveFileProgress progress)
{
bool ret = false;
if (Directory.Exists(path))
{
//主要是防止有重名文件
string savepath = GetPath(path, filename); //得到文件路径
//缓冲区
byte[] file = new byte[m_maxpacket];
int count = 0; //每次接收的实际长度
int receivedata = m_maxpacket; //每次要接收的长度
long offset = 0; //循环接收的总长度
long lastdata = size; //剩余多少还没接收
int mark = 0;
using (FileStream fs = new FileStream(savepath, FileMode.OpenOrCreate, FileAccess.Write))
{
if (size > 0)
{
while (true)
{
if (lastdata < receivedata)
{
receivedata = Convert.ToInt32(lastdata);
}
count = socket.Receive(file, 0, receivedata, SocketFlags.None);
if (count > 0)
{
fs.Write(file, 0, count);
offset += count;
lastdata -= count;
mark = 0;
}
else
{
mark++; //连续5次接收为0字节 则跳出循环
if (mark ==10)
{
break;
}
}
//接收进度
if (progress != null)
{
progress(Convert.ToInt32(((Convert.ToDouble(offset) / Convert.ToDouble(size)) * 100)));
}
//接收完毕
if (offset == size)
{
ret = true;
break;
}
}
}
fs.Close();
}
}
return ret;
}
public static bool ReceiveFile(Socket socket, string path, string filename, long size)
{
return ReceiveFile(socket, path, filename, size,null);
}
/// <summary>
/// 预先不知道文件名和文件大小 用此方法接收
/// 此方法对于的发送方法是SendFile()
/// </summary>
/// <param name="socket"></param>
/// <param name="path">要保存的目录</param>
public static void ReceiveFile(Socket socket, string path)
{
//得到包头信息字节数组 (文件名 + 文件大小 的字符串长度)
//取前8位
byte[] info_bt = ReceiveFixData(socket, 8);
//得到包头信息字符长度
int info_length = GetPacketLength(info_bt);
//提取包头信息,(文件名 + 文件大小 的字符串长度)
byte[] info = ReceiveFixData(socket, info_length);
//得到文件信息字符串 (文件名 + 文件大小)
string info_str = System.Text.Encoding.UTF8.GetString(info);
string[] strs = info_str.Split('|');
string filename = strs[0]; //文件名
long length = Convert.ToInt64(strs[1]); //文件大小
//开始接收文件
ReceiveFile(socket, path, filename, length);
}
private static int GetPacketLength(byte[] length)
{
string str = System.Text.Encoding.UTF8.GetString(length);
str = str.TrimEnd('*'); ;//("

