Packaged the DLL of the P2P connection and data transmission process (1)

zhaozj2021-02-16  51

Written in front

Psersocket.dll (hereinafter referred to as DLL) The connection procedure of the P2P connection and the method of transmitting information are encapsulated in the DLL, so that the process of developing P2P is relatively simple and standardized because the data stream is used. Objects, so that the transmission of data is relaxed and intuitive, so that the developer does not need to interpret one of the strings, and can fully utilize the Windows's asynchronous message mechanism directly to process one of the instruction objects. The DLL uses a custom set of data streams to transmit and synthesize instructions, without serializing objects using VC, avoiding problems with VC serialized objects that cannot be synthesized on different language platforms. The DLL data stream object can be freely transmitted between VC and Java, thereby making developers without the complex problem when multi-platform transmission. The DLL encapsulates the details of establishing connection and transfer information, making the P2P products developed by different developers to connect to each other, even if international standardized lack, only need to re-download the new DLL, without a need for each Developers have to override the program. With the increase and improvement of new features of DLL, each developer can directly integrate these functions into the original software, which will greatly accelerate the speed and reliability of development. The DLL has very powerful scalability, which interacts with the external callback function and the outside, which allows developers to get the current operation of the program at any time. The establishment of the P2P network is not one or several companies that can be completed. Only the joint efforts of all developers can build China's own P2P network.

Use the DLL to establish the steps you need to use the DLL to create a chat connection or transfer, the connection to receive the file is very easy, you only need to follow the steps: 1 Initialize the DLL. Implemented by calling the following methods and setting properties. PDEfine :: sinitsocketStream (); pthreadparm :: ScreatetCplistenport (1500); // 1500 is your own listening port number. PDEFINE :: csmsginfo.pwnd = this; pdefine :: csmsginfo.bisautodel = false;

PDEfine :: psgetfriendcallbackfun = cppserdlg :: sgetFriendFromid; / * A callback function is a static method in the CPPSerDLG class. DLL passes the ID number of a friend to this callback function to get the pointer to the PFRIEND object of the friend. When testing, you can fix a pointer to the created PFRIEND object. * / Pdefine :: psgetfilencallbackfun = cppserdlg :: sgetFileNameByFileId; / * A callback function is a static method in the CPPSerDLG class. DLL passes the digital identifier of a file to this callback function, to get the specific file name, including the path and extension, is the name of the file you want to transmit to the connected side. When testing, you can fix a file that performs a transfer test. This file is preferably tens of megabytes because the download speed will be very fast. * / 2 In response to 2 messages in your window. CREATE_NEW_OBJ_MSG / / In the response function of the message, call PDEfine :: ScreateNewobj (WPARAM, LPARAM) static method directly. CREATE_NEW_THREAD_MSG / / In the response function of the message, call PDEfine :: ScreateNewThread (WPARAM, LPARAM) static method directly in the response function. 3 Create a PFRIEND object, populate the three properties of the PFRIEND object: m_lpszhostaddress; // The host address of the connector. M_nhostport; // The listening port of the host of the connector. M_sfriendid; // Friends ID, you can set a 12-bit long string when testing. 4 Create a PRECVINFO structure. (If you want to create a chat connection, jump directly to step 6.) precvinfo * prf = new precvinfo (); prf-> szblockmap = null; // fixed assignment is NULL. PRF-> nfilelen = 110273244; // Want to download the total number of bytes of files. PRF-> nsplitno = 30; // Slide the file into how many blocks download, value from 1..999. PRF-> SSAVENAME = "E: // Test // CS1004"; // Saved file name, does not contain extensions. PRF-> Sexpendname = ". Exe"; // file extension.

5 Create a PTHREADPARM object to create a process of receiving the file. PTHReadparm * PTP = new pthreadparm (); PTP-> setMaxthreadNO (5); // Set the maximum number of threads when downloading. PTP-> m_precvinfo = prf; / / The pointer to the precvinfo structure created in front. PTP-> m_pfriend = cppserdlg :: sgetFriendFromid ("PPQ123456789"); // The pointer of the connected PFRIEND object. // Start downloading with the identity of the received. PTP-> StartThread (Recv_Type); // Start downloading with the received identity. The above process can create a connection to the PFRIEND object, and complete the download of a file. 6 Create a PTHReadParm object to create a chat connection. PTHREADPARM * PTP = new pthreadparm (); ptp-> m_pfriend = cppserdlg :: sgetFriendFromid ("PPQ123456789"); // The pointer of the connected PFRIEND object. PTP-> StartThread (chat_type); // Create a chat connection. It should be clear that the process of creating a connection is so simple. Of course, the above process olves a lot of details so you can't respond to the notification message issued by the DLL. This is used by the developer, so the DLL provides a large number of interfaces, and during operation, you also need to respond to some messages to set some parameters. Below I will introduce the use of classes defined in the DLL step by step. The DLL work mode DLL interacts with the outside, if you want to use this DLL correctly, you need to know the four classes defined in the DLL, and the callback function and structure, understand each message sent to the external window. Meaning.

The classes defined in the class DLL defined in the DLL have four: PDEfine, Pfriend, PBaseAct, PthreadParm. PDEfine defines some messages and static methods that need to be used, callback functions, constants, and DLL definitions. This class does not need to create an instance, and it is a static method, attribute, and some definitions. Pfriend wants to establish a connection to the party called a friend, every friend must have a PFRIEND object, and record the unique identifier of this friend in this object, his IP address, listening port and other related information. PBaseACT is a base class that can be converted into a directive object that can be transferred to the data stream. When the user needs to customize the transfer object, it is necessary to generate a new class from that class. PTHREADPARM describes and records one or a set of connections, which is a class that must be used when creating a connection. As long as you hold these 4 classes, you will grasp this DLL.

How to use this DLL? Below is an instance using this DLL, the specific program can refer to the PPSer project that is sent. The first step: initialize the DLL. Complete the initialization of the DLL by calling the static method in the PDefine class and setting some of the statically attributes. 1 PDefine :: SInitSocketStream (); 2 PThreadParm :: SCreateTCPListenPort (1500); 3 PBaseAct :: SSetUserGetObject (CPPSerDlg :: UserGetObject); 4 PDefine :: cSMsgInfo.pWnd = this; 5 PDefine :: cSMsgInfo.bIsAutoDel = false; 6 PDEfine :: psgetfriendcallbackfun = cppserdlg :: sgetFriendFromid; 7 pdefriendfromid; 7 pdefine :: psgetfilencallbackfun = cppserdlg :: sgetfilenamebyfileid; 第 s 第 初; 语 语;;;;;;;;;;;;;;;;;;;; This must be called first. Line 2 is used to create a TCP listening port, the parameters of the method are used to specify the listening port number you want to create. Line 3 sets the pointer to the callback function you need to use. The callback function is defined in PDEfine. This type of callback function is gocallback, and the return value is cruntimeclass *. It is declared in pdefine as: typedef cruntimeclass * (Byte NTYPE, LPCTSTSTSTST; it returns CruntimeClass * of the specified object by passing two parameters. Here, this function is defined as a static method in cppserdlg, which is defined in the cppserdlg.h file as follows: static cruntimeclass * WinAPI UsergetObject (Byte NTYPE, LPCTSTSTS;); About this function, will introduce later . The fourth line fills the value in the PRECVINFO structure, which saves the pointer to the window of the response message, and the structure is defined in PDEfine. The window pointer saved in the PDEfine :: csmsginfo variable is a pointer to the window used to respond to some of the key messages in the DLL. The 5th line indicates whether the structure will be automatically deleted by the DLL, specifying FALSE means that it is not automatically deleted by the DLL. Chain 6 sets a pointer to a callback function. The type of this function is getPalCallback, and the return value is pfriend *. It is declared in pdefine as: typedef pfriend * (lpctstr szfriendid); this function returns a pointer to a PFRIEND * object based on the ID number passed. Here, this function is defined as a static method in cppserdlg, which is defined in the cppserdlg.h file as follows: Static Pfriend * WinAPI SgetFriendFromid (LPCTSTR SID); About this function, will be described later. Chain 7 sets a pointer to a callback function. This function is GetFilencallback, and the return value is not.

It is declared in PDEfine as: typedef voidback (int NfileInd, PFriend * Pfriend, CString & Sfilen); This function returns a NFileID corresponding to the actual file name corresponding to the NFILEID file number identifier according to the file number ID passed. In this function, you can learn the ID of the friend who wants to get the file by passing the second parameter PFRIEND, check whether the other party has permission to get the file. If there is permission, the actual file name is filled in The third parameter sfilen; otherwise set sfilen = "". It is defined in the cppserdlg.h file as follows: Static Void WinAPI SgetFileNamebyFileId (int NfileID, PFriend * Pfriend, CString & Sfilen); About this function of this function, will be introduced later. Step 2: Creating a friend object PFriend Each PFRIEND object represents a friend capable of establishing a connection, in which you must fill in the ID number, IP address, and listening port number, then put this PFRIEND object into a list or Save in Map. In the cppserdlg :: SgetFriendFromid (LPCTSTR SID) method, you need to retrieve the object in the list or map of the PFRIEND object, and then return pfriend *; if not, return NULL. After receiving a connection request at the listening port, you will have a handshake with the request connection to confirm the identity of both parties. During this handshake, the backup function is called to confirm if the other party is connected enough. If NULL is returned, it is considered that the other party does not have access to the connection, the connection will be disconnected. If you want to respond to any connection request, you need to find the PFRIEND object when you retrieve it, then dynamically create a PFRIEND object, then join the list. Step 3: Create a structure of the file that receives the file, suitable for connection type to rec_type (if your connection type is send_type, please skip this step, if you want to build the connection type for chat_type, please jump directly to the 7th Step) precvinfo * prf = new precvinfo (); prf-> szblockmap = null; / / fixed assignment is NULL, the DLL will populate the specific value. PRF-> nfilelen = 110273244; // Want to download the total number of bytes of files. PRF-> nsplitno = 30; // The number of blocks will be split. PRF-> SSAVENAME = "E: // Test // CS1004"; // Download the file name saved, including the path, but does not include the extension. PRF-> Sexpendname = ". Exe"; // download the file extension.

Nfilelen means that you want to download the size of the file, this byte you need to get in other ways, when you create a precvinfo structure, you must fill in a correct value. Nsplitno indicates that the file is dynamically divided into multiple blocks to download. You can dynamically split a large file into several small blocks, and then use a synthetic function to merge files downloaded into a file into a file. Using this method is to respond to the future extension, the method of downloading the segmentation block will be provided later, if a certain download block occurs, only this download block can be transmitted. Another reason not to use a big file is to avoid a delay problem generated when establishing a large file. In the future extension, you can save a large file split block on a different hard disk. SEXPENDNAME indicates the extension of the file you want to download, which should be obtained from the transfer party, and the extension of the file transmitted by the transmit party is the same, and the recipient cannot modify this value. Step 4: Create a PTHReadParm object and start the received file. PTHREADPARM * PTP = new pthreadparm (); PTP-> SetMaxthreadNO (5); // Set the maximum number of threads that open at the same time of the download task is 5. PTP-> M_DWIDENTIFY = (DWORD) PTP; // pthreadparm number identifier can be the address of the object. PTP-> nfileid = 150; // indicates the digital identifier of the received file. PTP-> m_precvinfo = prf; // Pointer to the receiving structure precvinfo. PTP-> m_pfriend = cppserdlg :: sgetFriendFromid ("PPQ123456789"); PTP-> m_pmsginfo = & pdefine :: csmsgInfo; // Receive the PMSGINFO structure of the delivery message. PTP-> StartThread (RECV_TYPE); // Start a receiving thread. The attribute m_dwidentify in the pthreadparm indicates the digital identity of the object, and you should find the PTHREADPARM object through this digital identity and clearly know if the object exists. Because the value of this identification will be the LPARAM parameter of the message that is passed to the window specified by M_PMsgInfo. You can build a list or demary to save the value of each pthreadparm. Once this object is delete, cancel from List or Deque, when the message is received, you can retrieve this value in List or Deque, such as checking Represents the object available; otherwise, it is not necessary to respond to the message, simply return 0.

Step 5: Response 2 messages in the form specified in the PDEfin :: CSMSGINFO structure. CREATE_NEW_OBJ_MSG Directly calls PDEfine :: ScreateNewobj (WPARAM, LPARAM) static methods in this message, passing 2 parameters WPARAM and LPARAM of the message response function, others do not have to do anything.

CREATE_NEW_THREAD_MSG This message is more complicated, and it is more important. Where the LPARAM parameters are saved are the pointers of the newly created or existing PTHReadParm object. You can learn whether the PTHReadParm object has been identified by judging pthreadparm-> m_nidentify == 0. If the value is 0, you need to set a unique identifier for this object. And you need to judge the type of object, if the type is RECV_TYPE, you need to fill the precvinfo structure according to PPARM-> M_NFileID, this time you are the party, this connection, maybe the other party actively transmits you A file, or the other party inside the firewall, and you are in the firewall, so the other party is actively connected, and the file ID represented by this m_nfileID is the digital identification of the file you requested to transfer the other party. To complete a received connection, you must set the corresponding properties in the Precvinfo structure. In addition, you also need to set the value of m_pmsginfo or m_pcallbackfun so that the object can generate callbacks. Finally, call the PDEfine :: ScreateNewThread () static method in the response function of the message, pass the WPARAM and LPARAM parameters. The response function reference method of this message is as follows: {pthreadparm * ppArm = (pthreadparm *) LParam; if (pparm-> m_dwidentify == 0) {// If it is created for the first time, that is, the object has not been identified. // Retrieve the pointer to the PTHReadParm object. PPARM-> M_DWIDENTIFY = LPARAM; PPARM-> m_pmsginfo = & pdefine :: csmsginfo; // puts the object in a queue. // If the object type is a reception type, you need to populate the precvinfo structure according to PPARM-> M_NFileID. IF (PPARM-> getthredType () == rec_type) {precvinfo * precvinfo = new precvinfo (); pparm-> m_precvinfo = precvinfo; // is filled in the following structure. // precvinfo-> nfilelen = // precvinfo-> nsplitno = // precvinfo-> sexpendname = // precvinfo-> ssavename =}} PDEfine :: ScreateNewThread (WPARAM, LPARAM); Return 0;}

Step 6: Complete the callback function set in the 7th line of the initialization DLL. Void WinAPI sgetFileNameByFileID (int NfileID, Pfriend * Pfriend, CString & sfilen) {// Check, whether it is a specified friend, if not, it is not allowed to download. IF (pfriend-> m_sfriendid) == "PPQ123456789") sfilen = "e: //cs1004.exe"; else sfilen = "";} Seventh step: Creating a chat PTHReadParm is more simple, you only need to specify Pfriend object and PMSGINFO structure pointer. PThreadParm * pt = new PThreadParm (); pt-> m_pFriend = CPPSerDlg :: SGetFriendFromID ( "PPQ123456789"); PMsgInfo * pmi = new PMsgInfo (); pmi-> pWnd = this; pmi-> bIsAutoDel = true; // to The PTHReadParm created a PMSGINFO structure, and the PMSGINFO structure is automatically deleted when PTHReadparm is deleted. Pt-> m_pmsginfo = PMI; // You can also assign the address of the PDEfine :: CSMsgInfo directly to the variable. PT-> StartThread (chat_type); After the above steps, you have completed all the callback functions that must be set and how to use the DLL process has a certain understanding. Here will continue to describe how to respond to DLL messages, and how to customize the command objects.

About PBASEACT Detective Class: Increases the definition of the type of PBaseAct derived class in the stdafx.h file: Enum {self1_obj = user_obj, // Defines the user type ID to Self1_obj self2_obj, // can add more type IDs . // user_obj is the minimum type identification number that the user-defined derived class can be used. / / The maximum identification number of derived class you can create is 255, and the type identifier is represented by bytes. } PBASEACT's derived class must overload the following three methods: Virtual Void SelfSerialize (CString & SRC) {PBaseAct :: InituniteValue (src); // The first sentence of this method must call the method. // Add a serialization of this class attribute. // Repeat the static method void SuniteValue (SRC, LPCTSTR VALUE), // Sequently transmitted the desired properties, and the value is a string (LPCTSTR) or integer (int) represented by the attribute you want to transmit.

PBaseAct :: SelfSerialize (SRC); // The last sentence of the method must call the base class. } Virtual Void InitObject (LPVOID DATA); {PBaseAct :: InitObject (data); // The first sentence of this method must invoke the method of the base class. // According to the order in which you serialize in the sequenced property, // call the static method int sgetValue (data, value) // in which value is the value of the attribute, can be a CString or Int type variable . 2 sgetValue () methods in // PBaseAct, one is the value of the string, one is the value of the intimate, / / ​​actually calls the method of obtaining a string, and then the function is converted inside. // sgetvalue () method returns the sequence number of the current attribute. The sequence number starts from 3. // The sequence number of 0 is the transmitter ID, 1 is the recipient ID, 2 is the version number of the object. These values ​​are automatically decomposed in the basic class. } Virtual byte getobjType () {return self1_obj; // Returns in the Self1Act Derivet class. // Returns Return Self2_Obj in Self2Act. } How to deal with custom PBaseAct derived class objects during receiving? The following is as an example in cppserdlg: (For details, please refer to the PPSer Example)

1 Establish a static method in the following functions or classes:

Increasing public methods in cppserdlg.h file: Static CruntimeClass * WinAPI UsergetObject (Byte NTYPE, LPCTSTSTS; Static Bool WinApi Parseuserobj);

The corresponding method is defined in the cppserdlg.cpp file as follows: CRUNTIMECLASS * WINAPI CPPSERDLG :: UsergetObject (Byte NTYPE, LPCTSTSTSTSZVERSION) {// Szversion Variable Save the version number of the object, can be judged by detecting the version number to determine if // It is the object you ask. if (szVersion == "# MySelfDefineObj" {switch (nType) {case SELF1_OBJ: return RUNTIME_CLASS (Self1Act); // Self1Act is PBaseAct custom derived class case SELF2_OBJ:. return RUNTIME_CLASS (Self2Act);}} else if ( Szverion == "# user1defineObj") {// Add support for objects created for other users. Switch (NTYPE) {copy self1_obj: return runtime_class (self1act); // Self1act is a custom PBASEACT derived class. Case Self2_obj: Return runtime_class (self2act);}} Return NULL;

BOOL WINAPI CPPSERDLG :: Parseuserobj (WPARAM WPARAM, LPARAM LPARAM) {// Where the low 8 bits of WPARAM represent the type ID of the object. WPARAM's high is temporarily reserved, which may be used later. // LPARAM is a pointer to a type identified object that can be converted to an object by forced converter. // Take Self1Act as an example: byte ntype = (byte) WPARAM; PBaseAct * PA = (PBaseAct *) lparam; // If the version number is used, pay attention to the difference between the version number. The object's version number is saved in the PA-> m_sversion. Switch (NTYPE) {CASE Self1_Obj: Self1Act * SA = (Self1Act *) Pa; / / The received instruction is processed below. Break; Case Self2_Obj: Self2Act * SA = (Self2Act *) Pa; / / / / The received instruction is processed below. Break;}} 2 Build a self-contained PBaseAct derived class, it is necessary to overload this method: Virtual getback * getParseactFunpointer () {return cppserdlg :: Parseuserobj;} You can also specify a different handler for each derive class, at this time There is no need to compare, each derived class handler is a static method in the derived class. 3 Need to call a method to set the callback object. PBaseAct :: setusergetObject (cppserdlg :: usergetObject); this call should be added to the initialization phase of the main program. 4 You can also set a window handle and a custom message, then send the message to the specified window by the program. Define a static PMSGINFO structure in the derived class, and then overload the method in PBaseACT getCallbackMsg () pmsginfo * getCallbackMsg () {return } 5 Whether it is transmitted or generated by the instruction object generated by reception Once you can modify the values ​​of the properties in the object, it is repeatedly sent, which is different from the C object stream.

6 Every developer can define a self-derived class, but the identity of the derived class is starting from user_obj, so how can you distinguish between derived class or other developers?

In the base class of PBaseAct, a character type variable m_sversion is defined. The user's version number is saved in this variable (regarding how to create a self-already version number, there is no sure, this version number has no length limit, in order not Make your own derive class and other developers' derivatives, you can define enough long, for example: consisting of 16 characters, using characters can be a..z, a..z, 0..9 , _ And , -, # symbol, please do not use other symbols. The version number makes the program not only support the developer's own objects, but also supports objects created by other developers without modifying the program.

Developers can pack their defined user objects and instruction parsers into a DLL, publish directly, hide specific implementation details, provide sufficient interface, so that other developers can directly call these objects to complete the specified features. When you publish your own derived class object, you must provide a unique version number. After reading the above content, you should have clear how to create your own derive class, each derived class can represent one or a set of instructions, this instruction object is not like the serialized object of the VC, it can be reused, if You modified the value of the object, and the modified value will be sent out. Of course, this object stream is not as strong as the serialized object of VC, and the object is temporarily only contains some simple types, such as CString, LPCTSTSTSTSTSTSTSTSTSTSTSTSTSTSTSTSTSTSTSTSTSTST, and the maximum length of the object cannot exceed 16850 bytes. . I will improve the target stream in the next version, enable it to support unlimited data and integrate language transmission and reception. I hope everyone has any opinions, I can always send me a letter.

DLL message

The following is a message that the user must respond, and the window in response to these messages is defined in the PDEfine :: CSMSGINFO structure. CREATE_NEW_OBJ_MSG = 29600, directly call the PDEfine :: ScreateNewobj () static method, pass the WPARAM and LPARAM parameters directly in the message function executive. Others don't have to do anything.

CREATE_NEW_THREAD_MSG,

Saved in the LPARAM parameter is a pointer to the newly created or already existing PTHReadParm object. You can learn whether the PTHReadParm object has been identified by judging pthreadparm-> m_nidentify == 0. If the value is 0, you need to set a unique identifier for this object. And you also need to judge the type of object. If the type is RECV_TYPE, you need to populate the PRECVINFO structure according to PPARM-> M_NFileID. In addition, you also need to set the value of m_pmsginfo or m_pcallbackfun so that the object can generate callbacks. Please refer to the example. Finally, call the PDEfine :: ScreateNewThread () static method in the response function of the message, pass the WPARAM and LPARAM parameters.

When you receive a message ending of a PTHReadParm object, you can decide whether you want to continue to use the object, if you want to continue using this object, first call the initValue () method, INITVALUE () will not change the original assignment, if you If you want to continue, you don't have to change the value that has been assigned, and the startthread () method is directly called. If you want to complete another job, you must set the value of the corresponding property, just like you have created a PTHREADPARM object, then call the startthread () method. If you don't want to continue using this object, you need DELETE object. If you don't want an object to delete the PRECVINFO object before DELETE, you can save the pointer of the object and set m_precvinfo = null.

All_connect_end_msg, all connection requests for a pthreadparm have been terminated and ask how to handle it. LPARAM Saves points to PTHREADPARM.

Mission_end_msg indicates that a PTHReadPar is ended, but its task has not been completed. LPARAM Saves points to PTHREADPARM. The reason for the termination work may be the interrupt issued by the user, or there has been a problem during the transfer process.

Mission_completed_msg indicates a PTHReadParm task to complete. LPARAM Saves points to PTHREADPARM. // The following is the message chat_connect_created_msg that the user can respond to, and a chat socket is established and has been connected to the friend object. The LPARAM parameter points to the pointer to the PFRIEND object with the chat. Do not delete the pointer.

Chat_closed_msg, a chat socket is turned off. The LPARAM parameter points to the pointer to the PFRIEND object with the chat. Do not delete the pointer. One_recv_thread_end_msg, one receiving thread ends. The value of the m_dwidentify attribute in the pthreadparm in the PTHReadparm where the LPARAM parameter is saved. The low 8 bits of the WPARAM parameter indicates the identification number of the thread in the PTHReadparm thread group.

One_send_thread_end_msg, one transfer thread ends. The value of the m_dwidentify attribute in the pthreadparm in the PTHReadparm where the LPARAM parameter is saved. The low 8 bits of the WPARAM parameter indicates the identification number of the thread in the PTHReadparm thread group.

Thread_max_no_created_msg, has created the maximum number of threads.

RECV_NEW_BLOCK_MSG, the receiving thread is ready to receive a newly allocated block number. The value of the m_dwidentify attribute in the pthreadparm in the PTHReadparm where the LPARAM parameter is saved. The low 8 bits of the WPARAM parameter indicates the identification number of the thread in the PTHReadparm thread group. You can call GetThreadIDinArray (Byte) WPARAM to get the pointer to the PThreadID object where the thread is located.

Send_new_block_msg, the transfer thread is ready to transmit a new part. The value of the m_dwidentify attribute in the pthreadparm in the PTHReadparm where the LPARAM parameter is saved. The low 8 bits of the WPARAM parameter indicates the identification number of the thread in the PTHReadparm thread group. You can call GetThreadIDinArray (Byte) WPARAM to get the pointer to the PThreadID object where the thread is located.

Recv_data_msg, received new data information. In the response function of the message, you need to set the properties m_bissendmsg =! M_bissendmsg in the PTHReadparm, otherwise the new message cannot be received. Saved in the m_dwcompletedlen attribute in the PThreadParm is the total number of bytes. The value of the m_dwidentify attribute in the pthreadparm in the PTHReadparm where the LPARAM parameter is saved. The low 8 bits of the WPARAM parameter indicates the identification number of the thread in the PTHReadparm thread group. You can call GetThreadIDinArray (Byte) WPARAM to get the pointer to the PThreadID object where the thread is located.

Send_data_msg, with the RECV_DATA_MSG message.

The messages sent by the DLL will continue to expand. For the use of the DLL, it is temporarily introduced here, and there is a corresponding description in the header files sent by the package, and a test is sent, this example is in the PPSer directory. PCHATATATATATAtact in the PPSer project is an instance of a user-defined object. In the sgetfilenamebyfileid () function in the cppserdlg.cpp file, Sfilen = "E: //cs1004.exe" changes this sentence to the existing file name you want to test. In the onTest () function body in the cppserdlg.cpp file, how to create an example of receiving threads and a chat thread, the file sender and the receiver are the user's own machine, modify the PRF-> SSAVENAME in the precvinfo structure. = "E: // Test // CS1004", you can change the location and file name of the file being saved after downloading, and change it to the corresponding directory and file name on your own machine. Modify Prf-> nfilelen = 110273244 This sentence is the size of the file you want to download in bytes. Re-compile the program, then click the Test button to start downloading, click the StartThread button, will send a chat message, the sending object is PChatAtact, click the StopThread button to abort the download thread. Re-click the TEST button, the breakpoint will be submitted to download. Note: After clicking the TEST button, do not click the Test button to click on the StopThread button, otherwise the download will not be normal. Chat Connection If no message is sent or received over a period of time, the connection will be automatically disconnected to release the resource.

You can connect with multiple PTHREADPARM objects and then call the STARTTHREAD () method of the object. The DLL will put your request in a queue, loop the connection test, if successful, start the thread or create a chat connection; if it is not successful, then re-put the connection request in the tail of the queue, then from the header of the queue Remove a connection request, repay it. The DLL fully utilizes Windows's asynchronous message mechanisms, only the connection is established, and after the verification is successful, the new thread will be created without creating a thread for each connection. When a threadset group is started, a plurality of threads belonging to the thread group will be requested in turn, which has a higher priority, which will first process the other connection requests.

Now just the first version of the DLL. In the next version, I will integrate voice transmission in the DLL, so that developers can use DLLs to directly develop software with voice chat function. I hope that everyone will use any issues or opinions encountered in the DLL development process, and I hope that more friends can join this development ranks and discuss this topic. Email: Wanghao0727@sohu.com

转载请注明原文地址:https://www.9cbs.com/read-25315.html

New Post(0)