A recent project uses point-to-point file transmission, so I am looking for materials everywhere. Program Finally, I finally finished it. In order to make others take less detours, I decided to contribute the most important part of the program, hoping to help everyone.
My program is divided into three parts, including the sending and receiving parts and a communication base class shared by the two. This base class is the result of my painstaking efforts :)
I. Communication Base
Using system;
Using system. net. Sockets;
Using system. net;
Using system. IO;
Using system. Windows. forms;
Using system. text;
Namespace baseclass
{
/// <Summary>
/// The message transmission format is the command part of the given length + the command comment part of the given length + the variable length information part
/// </Summary>
Public class communclass
{
Public communclass ()
{
//
// Todo: add the constructor logic here
//
}
/// <Summary>
/// Command part length
/// </Summary>
Private Static readonly int jsonlen = 50;
/// <Summary>
/// Length of the comment part
/// </Summary>
Private Static readonly int desclen = 100;
/// <Summary>
/// The number of bytes occupied by the variable length part
/// </Summary>
Private Static readonly int dynamiclengthlen = 10;
/// <Summary>
/// The length of the variable information part processed each time
/// </Summary>
Private Static readonly int deallen = 1024;
/// <Summary>
//// Maximum response Length
/// </Summary>
Private Static readonly int responlen = 20;
/// <Summary>
/// Fill in characters that are not long enough for commands or comments
/// </Summary>
Private Static readonly char fillchar = '^ ';
/// <Summary>
/// The callback method after a part of the data is successfully sent (it can also be considered as a trigger event, but not strictly)
/// </Summary>
Public Delegate void onsend (INT itotal, int isending );
/// <Summary>
/// Establish a connection based on the given server and port number
/// </Summary>
/// <Param name = "strhost"> server name </param>
/// <Param name = "iport"> port number </param>
/// <Returns> </returns>
Public static socket connecttoserver (string strhost, int iport)
{
Try
{
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 ("An error occurred while establishing a connection to the server" + E. Message ));
}
}
/// <Summary>
/// Write the text to the socket
/// </Summary>
/// <Param name = "S"> socket for sending information </param>
/// <Param name = "strinfo"> information to be sent </param>
/// <Returns> Successful </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 ("failed to send text! "+ Err. Message );
Return false;
}
}
/// <Summary>
/// Write the command text to the socket
/// </Summary>
/// <Param name = "S"> socket for sending command text </param>
/// <Param name = "strinfo"> command text to be sent </param>
/// <Returns> Successful </returns>
Public static bool writecommandtosocket (socket S, string strcmd)
{
If (strcmd = "")
Strcmd = "NOP ";
Strcmd = strcmd. padright (FIG, fillchar );
Return writetexttosocket (S, strcmd );
}
/// <Summary>
/// Write the command annotation to the socket
/// </Summary>
/// <Param name = "S"> socket for sending command comments </param>
/// <Param name = "strinfo"> command comment to be sent </param>
/// <Returns> Successful </returns>
Public static bool writecommanddesctosocket (socket S, string strdesc)
{
If (strdesc = "")
Strdesc = "0 ";
Strdesc = strdesc. padright (desclen, fillchar );
Return writetexttosocket (S, strdesc );
}
/// <Summary>
/// Number of bytes for sending variable information
/// </Summary>
/// <Param name = "S"> socket of the number of bytes to be sent </param>
/// <Param name = "ilen"> Number of bytes </param>
/// <Returns> Successful </returns>
Public static bool writedynamiclentosocket (socket S, int ilen)
{
String strlen = ilen. tostring (). padright (dynamiclengthlen, fillchar );
Return writetexttosocket (S, strlen );
}
/// <Summary>
/// Send the specified part of the cache to the socket
/// </Summary>
/// <Param name = "S"> socket for sending cache </param>
/// <Param name = "Buf"> cache to be sent </param>
/// <Param name = "istart"> Start position of the cache to be sent </param>
/// <Param name = "icount"> Number of bytes to be sent to the cache </param>
/// <Param name = "iblock"> byte description sent each time </param>
/// <Param name = "sendsuccess"> callback function after each successful sending </param>
/// <Returns> whether the message is sent successfully </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>
/// Send unfixed-length text to the socket
/// </Summary>
/// <Param name = "S"> socket for sending text </param>
/// <Param name = "strtext"> text to be sent </param>
/// <Param name = "onsendtext"> callback function after a part of the text is successfully sent </param>
/// <Param name = "settextlen"> get the callback function of the text length. </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 ("failed to send text! "+ Err. Message );
Return false;
}
}
/// <Summary>
/// Write the file to socket
/// </Summary>
/// <Param name = "S"> socket of the file to be sent </param>
/// <Param name = "strfile"> file to be sent </param>
/// <Returns> Successful </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 ("failed to send file! "+ Err. Message );
Return false;
}
Finally
{
FS. Close ();
}
}
/// <Summary>
/// The recipient's simple response to his message
/// </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>
/// Read the command from the socket
/// </Summary>
/// <Param name = "S"> socket for reading the command </param>
/// <Returns> READ command </returns>
Public static string readcommandfromsocket (socket S)
{
Byte [] bufcmd = new byte [comment Len];
Int icount = S. Receive (bufcmd, 0, Len, socketflags. Partial );
String strcommand = encoding. utf8.getstring (bufcmd, 0, Len );
Return strcommand = strcommand. trimend (fillchar );
}
/// <Summary>
/// READ command comments
/// </Summary>
/// <Param name = "S"> socket for reading command comments </param>
/// <Returns> comments of the read command </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>
/// Read the length of the variable part
/// </Summary>
/// <Param name = "S"> socket to read the variable part length </param>
/// <Returns> length of the variable part to be read </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>
/// Read variable information in text format
/// </Summary>
/// <Param name = "S"> socket to read variable information </param>
/// <Returns> variable information read </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>
/// Read variable information in the file format
/// </Summary>
/// <Param name = "S"> socket to read variable information </param>
/// <Param name = "strfile"> storage location of the Read File </param>
/// <Returns> whether the read is successful </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 ("failed to receive file" + err. Message );
Return false;
}
Finally
{
FS. Close ();
}
}
} // End class
} // End namespace