首页 > 开发 > 综合 > 正文

使用C#进行点对点通讯和文件传输(通讯基类部分)

2024-07-21 02:25:06
字体:
来源:转载
供稿:网友
最近一个项目要用到点对点文件传输,俺就到处找资料写程序,最后终于完成了,为了让别人少走些弯路,俺决定将俺程序中最重要的部分贡献出来,希望对大家有所帮助。



俺的程序分三部分,包括发送部分、接受部分和一个两者共享的通讯基类,这个基类才是俺心血的结晶:)



一、通讯基类

using system;

using system.net.sockets;

using system.net ;

using system.io ;

using system.windows.forms;

using system.text;



namespace baseclass

{

/// <summary>

/// 传送信息的格式为 给定长度的命令部分+给定长度的命令注释部分+可变长度的长度信息+可变长度的信息部分

/// </summary>

public class communclass

{

public communclass()

{

//

// todo: 在此处添加构造函数逻辑

//

}

/// <summary>

/// 命令部分的长度

/// </summary>

private static readonly int cmdlen = 50 ;

/// <summary>

/// 命令注释部分的长度

/// </summary>

private static readonly int desclen = 100 ;

/// <summary>

/// 可变长度的长度信息部分所占的字节数

/// </summary>

private static readonly int dynamiclengthlen = 10 ;

/// <summary>

/// 每次处理可变信息部分的长度

/// </summary>

private static readonly int deallen = 1024 ;

/// <summary>

/// /应答的最大长度

/// </summary>

private static readonly int responlen = 20 ;

/// <summary>

/// 用于填充命令或注释不足长度部分的字符

/// </summary>

private static readonly char fillchar = '^' ;



/// <summary>

/// 成功发送一部分数据后的回调方法(也可以认为是触发的事件,但严格来说还不是)

/// </summary>

public delegate void onsend(int itotal,int isending) ;



/// <summary>

/// 根据给定的服务器和端口号建立连接

/// </summary>

/// <param name="strhost">服务器名</param>

/// <param name="iport">端口号</param>

/// <returns></returns>

public static socket connecttoserver(string strhost,int iport)

{

try

{

ipaddress ipaddress = dns.resolve(strhost).addresslist[0];

ipendpoint ippoint = new ipendpoint(ipaddress,iport) ;



socket s = new socket(addressfamily.internetwork,sockettype.stream,protocoltype.tcp) ;

s.connect(ippoint) ;

return s ;

}

catch (exception e)

{

throw (new exception("建立到服务器的连接出错" + e.message)) ;

}

}

/// <summary>

/// 将文本写到socket中

/// </summary>

/// <param name="s">要发送信息的socket</param>

/// <param name="strinfo">要发送的信息</param>

/// <returns>是否成功</returns>

public static bool writetexttosocket(socket s,string strinfo)

{

byte [] buf = encoding.utf8.getbytes(strinfo) ;

try

{

s.send(buf,0,buf.length,socketflags.none) ;

return true ;

}

catch(exception err)

{

messagebox.show("发送文本失败!"+err.message) ;

return false ;

}

}

/// <summary>

/// 将命令文本写到socket中

/// </summary>

/// <param name="s">要发送命令文本的socket</param>

/// <param name="strinfo">要发送的命令文本</param>

/// <returns>是否成功</returns>

public static bool writecommandtosocket(socket s,string strcmd)

{

if (strcmd == "")

strcmd = "nop" ;

strcmd = strcmd.padright(cmdlen,fillchar) ;

return writetexttosocket(s,strcmd) ;

}

/// <summary>

/// 将命令注释写到socket中

/// </summary>

/// <param name="s">要发送命令注释的socket</param>

/// <param name="strinfo">要发送的命令注释</param>

/// <returns>是否成功</returns>

public static bool writecommanddesctosocket(socket s,string strdesc)

{

if (strdesc == "")

strdesc = "0" ;

strdesc = strdesc.padright(desclen,fillchar) ;

return writetexttosocket(s,strdesc) ;

}

/// <summary>

/// 发送可变信息的字节数

/// </summary>

/// <param name="s">要发送字节数的socket</param>

/// <param name="ilen">字节数</param>

/// <returns>是否成功</returns>

public static bool writedynamiclentosocket(socket s,int ilen)

{

string strlen = ilen.tostring().padright(dynamiclengthlen,fillchar) ;

return writetexttosocket(s,strlen) ;

}

/// <summary>

/// 将缓存的指定部分发送到socket

/// </summary>

/// <param name="s">要发送缓存的socket</param>

/// <param name="buf">要发送的缓存</param>

/// <param name="istart">要发送缓存的起始位置</param>

/// <param name="icount">要发送缓存的字节数</param>

/// <param name="iblock">每次发送的字节说</param>

/// <param name="sendsuccess">每次发送成功后的回调函数</param>

/// <returns>是否发送成功</returns>

public static bool writebuftosocket(socket s,byte [] buf,int istart,int icount,int iblock,onsend sendsuccess)

{

int isended = 0 ;

int isending = 0 ;

while(isended<icount)

{

if (isended + iblock <= icount)

isending = iblock ;

else

isending = icount - isended ;

s.send(buf,istart+isended,isending,socketflags.none) ;

isended += isending ;

if (readresponsionfromsocket(s)=="ok")

if (sendsuccess != null)

sendsuccess(icount,isended) ;

else

return false;

}

return true ;

}

/// <summary>

/// 将长度不固定文本发送到socket

/// </summary>

/// <param name="s">要发送文本的socket</param>

/// <param name="strtext">要发送的文本</param>

/// <param name="onsendtext">成功发送一部分文本后的回调函数</param>

/// <param name="settextlen">得到文本长度的回调函数</param>

/// <returns></returns>

public static bool writedynamictexttosocket(socket s,string strtext,

onsend onsendtext)

{

byte [] buf = encoding.utf8.getbytes(strtext) ;



int ilen = buf.length ;

try

{

writedynamiclentosocket(s,ilen) ;

return writebuftosocket(s,buf,0,ilen,deallen,onsendtext) ;

}

catch(exception err)

{

messagebox.show("发送文本失败!"+err.message) ;

return false ;

}

}

/// <summary>

/// 将文件写到socket

/// </summary>

/// <param name="s">要发送文件的socket</param>

/// <param name="strfile">要发送的文件</param>

/// <returns>是否成功</returns>

public static bool writefiletosocket(socket s,string strfile,

onsend onsendfile)

{

filestream fs = new filestream(strfile,filemode.open,fileaccess.read,fileshare.read) ;

int ilen = (int)fs.length ;

writedynamiclentosocket(s,ilen) ;

byte [] buf = new byte[ilen] ;

try

{

fs.read(buf,0,ilen) ;

return writebuftosocket(s,buf,0,ilen,deallen,onsendfile) ;

}

catch(exception err)

{

messagebox.show("发送文件失败!"+err.message) ;

return false ;

}

finally

{

fs.close() ;

}

}

/// <summary>

/// 对方对自己消息的简单回应

/// </summary>

/// <param name="s"></param>

/// <returns></returns>

public static string readresponsionfromsocket( socket s)

{

byte [] bufcmd = new byte[responlen] ;

int icount = s.receive(bufcmd) ;

string strrespon = encoding.utf8.getstring(bufcmd,0,icount) ;

return strrespon ;

}

/// <summary>

/// 从socket读取命令

/// </summary>

/// <param name="s">要读取命令的socket</param>

/// <returns>读取的命令</returns>

public static string readcommandfromsocket( socket s)

{

byte [] bufcmd = new byte[cmdlen] ;

int icount = s.receive(bufcmd,0,cmdlen,socketflags.partial) ;

string strcommand = encoding.utf8.getstring(bufcmd,0,cmdlen) ;

return strcommand = strcommand.trimend(fillchar) ;

}

/// <summary>

/// 读取命令注释

/// </summary>

/// <param name="s">要读取命令注释的socket</param>

/// <returns>读取的命令注释</returns>

public static string readcommanddescfromsocket( socket s)

{

byte [] bufcmd = new byte[desclen] ;

int icount = s.receive(bufcmd,0,desclen,socketflags.partial) ;

string strcommand = encoding.utf8.getstring(bufcmd,0,desclen) ;

return strcommand = strcommand.trimend(fillchar) ;

}

/// <summary>

/// 读取可变部分的长度

/// </summary>

/// <param name="s">要读取可变部分长度的socket</param>

/// <returns>读取的可变部分的长度</returns>

public static int readdynamiclenfromsocket( socket s)

{

byte [] bufcmd = new byte[dynamiclengthlen] ;

int icount = s.receive(bufcmd,0,dynamiclengthlen,socketflags.partial) ;

string strcommand = encoding.utf8.getstring(bufcmd,0,dynamiclengthlen) ;

return int.parse(strcommand.trimend(fillchar)) ;

}

/// <summary>

/// 读取文本形式的可变信息

/// </summary>

/// <param name="s">要读取可变信息的socket</param>

/// <returns>读取的可变信息</returns>

public static string readdynamictextfromsocket( socket s)

{

int ilen = readdynamiclenfromsocket(s) ;



byte [] buf = new byte[ilen] ;

string strinfo = "" ;



int ireceiveded = 0 ;

int ireceiveing = 0 ;

while(ireceiveded<ilen)

{

if (ireceiveded + deallen <= ilen)

ireceiveing = deallen ;

else

ireceiveing = ilen - ireceiveded ;

s.receive(buf,ireceiveded,ireceiveing,socketflags.none) ;

communclass.writetexttosocket(s,"ok") ;

ireceiveded+= ireceiveing ;

}



strinfo = encoding.utf8.getstring(buf,0,ilen) ;



return strinfo ;

}

/// <summary>

/// 读取文件形式的可变信息

/// </summary>

/// <param name="s">要读取可变信息的socket</param>

/// <param name="strfile">读出后的文件保存位置</param>

/// <returns>是否读取成功</returns>

public static bool readdynamicfilefromsocket( socket s,string strfile)

{

int ilen = readdynamiclenfromsocket(s) ;

byte [] buf = new byte[ilen] ;

filestream fs = new filestream(strfile,filemode.create,fileaccess.write) ;



try

{

int ireceiveded = 0 ;

int ireceiveing = 0 ;

while(ireceiveded<ilen)

{

if (ireceiveded + deallen <= ilen)

ireceiveing = deallen ;

else

ireceiveing = ilen - ireceiveded ;

s.receive(buf,ireceiveded,ireceiveing,socketflags.none) ;

communclass.writetexttosocket(s,"ok") ;

ireceiveded+= ireceiveing ;

}

fs.write(buf,0,ilen) ;

return true ;

}

catch(exception err)

{

messagebox.show("接收文件失败"+err.message) ;

return false ;

}

finally

{

fs.close() ;

}

}

}//end class

}//end namespace

上面是俺的通讯基础类,有了这个类,再进行发送接受还不是小菜一碟吗?

未完待续



发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表