Delphi socket connection. Net socket

Source: Internet
Author: User
 

Over the past few days, I have been studying the socket program connected to. Net by Delphi, and finally made some progress.

Requirements:

The server intercepts the first four bytes and converts them to numbers. The second digit is the Business Code. It determines which business logic to call.

Using system; using system. collections. generic; using system. text; using system. io; using system. net. sockets; using system. threading; using pivasupdate; using log4net; using system. reflection; using system. net; namespace pivasupdate {public class serviceprocess {private const int length = 1024; private const int getversion = 1; private const int downloadnew = 2; private const int downloadfile = 3; Public stat IC autoresetevent alldone = new autoresetevent (false); Private Static readonly ilog = logmanager. getlogger (methodbase. getcurrentmethod (). declaringtype); Private string cliendaddres; private string installpath = configutils. getwindowsserviceinstallpath (configutils. servicename); Public void processcallback (iasyncresult AR) {socket handler = NULL; try {stateobject state = (stateobject) ar. asyncs Tate; handler = state. worksocket; cliendaddres = IPaddress. parse (ipendpoint) handler. remoteendpoint ). address. tostring () + ":" + (ipendpoint) handler. remoteendpoint ). port. tostring () + ":"; int bytesread = handler. endreceive (AR); log. info (cliendaddres + "received packet size:" + bytesread + "Byte"); int control = bitconverter. toint32 (state. buffer, 0); string c = utf8encoding. utf8.getstring (state. buffer, 4, byte Sread-4); Switch (Control) {Case getversion: log. info (cliendaddres + "get the latest version, request version:" + C); getversionno (C, Handler); break; Case downloadnew: log. info (cliendaddres + "download and update the configuration file:" + installpath + "/" + C); downloadnew (C, Handler); break; Case downloadfile: log. info (cliendaddres + "download file," + installpath + "/" + C); downloadfile (installpath + "/" + C, Handler); break; default: break ;}} catch (exception E) {Log. Error (cliendaddres + "program error," + E. Message) ;}finally {If (handler! = NULL) {handler. Shutdown (socketshutdown. Both); handler. Close (); handler = NULL; log. Info ("disconnected from client:" + cliendaddres +. ") ;}} Public void downloadfile (string filepath, socket handler) {If (! File. exists (filepath) {string fail = "the file does not exist."; log. Info (cliendaddres + "Access File:" + filepath + "does not exist. "); Byte [] failbytes = encoding. utf8.getbytes (fail); handler. beginsend (failbytes, 0, failbytes. length, 0, new asynccallback (sendcallback), Handler); alldone. waitone (); return;} handler. beginsendfile (filepath, new asynccallback (delegate (iasyncresult AR) {handler. endsendfile (AR); alldone. set (); log. info (cliendaddres + "Sending File:" + filepath + "success. ") ;}), Handler); alldone. waitone ();} public void downloadne W (string versioncode, socket handler) {string [] STRs = versioncode. split ('. '); string result = ""; List <byte> resbyte = new list <byte> (); If (STRs. length! = 3) {result = "version number error"; log. warn (cliendaddres + "version number error," + versioncode); resbyte. addrange (encoding. utf8.getbytes (result); handler. beginsend (resbyte. toarray (), 0, resbyte. count, 0, new asynccallback (sendcallback), Handler); return;} filestream stream = file. openread (installpath + "/version/" + versioncode + "/update. XML "); List <byte> List = new list <byte> (); int COUNT = 0; byte [] Buf = new byte [1024]; While (COUNT = stream. read (BUF, 0, Buf. length)> 0) list. addrange (BUF); handler. beginsendfile (installpath + "/version/" + versioncode + "/update. XML ", new asynccallback (delegate (iasyncresult AR) {handler. endsendfile (AR); log. info (cliendaddres + "file sent successfully, file name update. XML "); alldone. set () ;}), Handler); alldone. waitone ();} public void getversionno (string content, socket handler) {string [] STRs = content. SP Trim ('.'); string result = ""; List <byte> resbyte = new list <byte> (); If (STRs. length! = 3) {result = "version number error"; log. warn (cliendaddres + "version number error," + content); resbyte. addrange (encoding. utf8.getbytes (result); handler. beginsend (resbyte. toarray (), 0, resbyte. count, 0, new asynccallback (sendcallback), Handler); return;} string [] dirs = directory. getdirectories (installpath + "/version"); For (INT I = 0; I <dirs. length; I ++) {If (dirs [I]. endswith ("\" + content) {if (I! = Dirs. length-1) {result = directory. createdirectory (dirs [I + 1]). name; break;} else {result = dirs [I] ;}} if (result = "") {resbyte. addrange (encoding. utf8.getbytes ("this version is not found. "); Log. warn (cliendaddres + "version not found:" + content);} else {resbyte. addrange (encoding. utf8.getbytes (result); log. info (cliendaddres + "Send new version:" + result);} handler. beginsend (resbyte. toarray (), 0, resbyte. count, 0, new asynccallback (sendcallback), Handler); alldone. waitone ();} private void sendcallback (iasyncresult AR) {try {// retrieve the socket from the State object. socket handler = (socket) ar. asyncstate; // complete sending the data to the remote device. int bytessent = handler. endsend (AR); log. info (cliendaddres + "sent successfully, number of bytes sent:" + bytessent); alldone. set ();} catch (exception e) {log. error (cliendaddres + "failed to send:" + E. message, e );}}}}

The above code is the server logic.

Delphi uses tclientsocket to connect to the server program.

There are several major problems.

Tclientsocket. sendbuf can send any character bytes and other data, but our idea is that the first four bytes are numbers followed by custom strings. Therefore, bytes need to be processed.

First, convert the number to a four-byte array, then convert the string to a UTF-8 encoded byte array, and then combine and send it. Unexpectedly, no results are returned after the program is successfully sent.

Then, the server traces the code and finds that the byte array order accepted by the server is messy and the number to be converted has failed. Therefore, no results are returned.

After searching for multiple reasons, we found that in Delphi, byte arrays use dynamic arrays of byte. When Delphi dynamic arrays pass through the socket buffer zone, data confusion occurs, how can this problem be solved?

It has been confirmed that the static array [1 .. 5] of byte can be sent successfully, and the server side can be decoded successfully.

However, if the data is dynamic and the length is not determined, this method is not applicable. Therefore, the program still needs to be improved. All the commands and data in this way are strings. The server first decodes, converts them to strings, and then parses the strings.

After studying the sendbuf method, we found that the first parameter requires a pointer type, and I passed an array. In principle, the two parameters have the same effect, is the address of the first element of the array, but this is obviously not the case. Directly treat the array as the address of the number array object returned by the parameter, while passing the first array element as the parameter will pass the address of the first element. Therefore, you can change the parameters.

Next, let's take a look at how Delphi sends commands using static arrays.

VaR arr2: tbytes; arr1: array [0 .. 14] of byte; seendtext: utf8string; rectext: widestring; begin MMO. lines. add ('sending directive '+ inttostr (1); with client do begin open; // setlength (arr1, 4); arr1 [0]: = 1; seendtext: = utf8encode ('1. 1302.1714 '); // setlength (arr1, length (arr1) + Length (seendtext); move (seendtext [1], arr1 [4], length (seendtext )); client. socket. sendbuf (arr1, length (arr1); rectext: = utf8decode (client. socket. receivetext); MMO. lines. add (rectext); close; end;

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.