Detailed description of csocket programming under MFC

Source: Internet
Author: User
Tags set socket

Detailed description of csocket programming under MFC:

1. common functions and precautions (for detailed descriptions of function interfaces, refer to msdn ):

Csocket: Create initialization (generally written to the serverProgramUse the following csocket: socket for initialization)

Csocket: Socket Initialization

Csocket: setsockopt set socket options

Csocket: bind bound address port

Csocket: connect connection

Csocket: Listen listener

Csocket: accept receives socket from external connection
 
Csocket: Send content

Csocket: receive received content

Csocket: close (not equal to delete)

1) when using MFC to write a socket program, the <afxsock. h> file must be included.

2) afxsocketinit () is a function that must be called before csocket is used. Otherwise, errors may occur when using csocket. In addition, this function has an important usage method,
This function must be called before csocket is used in a thread. Even if the main thread calls this function, the function must be called first in the subthread to use csocket.

3) Note that the create method already contains the bind method. If the bind method is initialized with the create method, the bind method cannot be called again, or an error may occur.

2. ExamplesCode, Through examples to learn how to use csocket for programming, and the attachment contains the complete example code. The example can be found in my release resources: MFC csocket programming example http://download.csdn.net/source/379597

1) main client code:

// Initialization
Afxsocketinit ();

// Create a csocket object
Csocket asocket;

Cstring strip;
Cstring strport;
Cstring strtext;

This-> getdlgitem (idc_edit_ip)-> getwindowtext (strip );
This-> getdlgitem (idc_edit_port)-> getwindowtext (strport );
This-> getdlgitem (idc_edit_text)-> getwindowtext (strtext );

// Initialize the csocket object. Because the client does not need to bind any port or address, use the default parameter.
If (! Asocket. Create ())
...{
Char szmsg [1024] =... {0 };

Sprintf (szmsg, "Create faild: % d", asocket. getlasterror ());

Afxmessagebox (szmsg );
Return;
}

// Convert the content type of the port to be connected
Int nport = atoi (strport );
 
// Connect the specified address and port
If (asocket. Connect (strip, nport ))
...{
Char szrecvalue [1024] =... {0 };

// Send content to the server
Asocket. Send (strtext, strtext. getlength ());

// Receives the content sent back by the server (this method will be blocked and will continue to be executed only after the content is received)
Asocket. Receive (void *) szrecvalue, 1024 );

Afxmessagebox (szrecvalue );
}
Else
...{
Char szmsg [1024] =... {0 };

Sprintf (szmsg, "Create faild: % d", asocket. getlasterror ());

Afxmessagebox (szmsg );
}

// Close
Asocket. Close ();

2) server code:

Unsigned int startserver (lpvoid lparam)
...{
// Initialize winscok
If (! Afxsocketinit ())
...{
Afxmessagebox (idp_sockets_init_failed );
Return 1;
}

M_exit = false;

Cserverdlg * adlg = (cserverdlg *) lparam;

cstring strport;
adlg-> getdlgitemtext (idc_edit_port, strport);
uint nport = atoi (strport );
// socket ------------------------------------------------
csocket asocket, serversocket;
// it is best not to use asocket. create, because 10048 errors may easily occur
If (! Asocket. socket ()
... {
char szerror [256] =... {0 };
sprintf (szerror, "Create faild: % d", getlasterror ();
afxmessagebox (szerror );
return 1;
}

Bool boptval = true;
Int boptlen = sizeof (bool );

// Set the socket option, which is required to solve the 10048 Error
Asocket. setsockopt (so_reuseaddr, (void *) & boptval, boptlen, sol_socket );
// Listen
If (! Asocket. Listen (10 ))
...{
Char szerror [256] =... {0 };

Sprintf (szerror, "Listen faild: % d", getlasterror ());

Afxmessagebox (szerror );

Return 1;
}

Cstring strtext;

Adlg-> getdlgitemtext (idc_edit_log, strtext );

Strtext + = "Server start! ";

Adlg-> setdlgitemtext (idc_edit_log, strtext );

while (! M_exit)
... {
// receives external connections
If (! Asocket. accept (serversocket)
... {
continue;
}< br> else
... {& lt; BR & gt; char szrecvmsg [256] =... {0 };
char szoutmsg [256] =... {0 };
// receives client content: blocked
serversocket. receive (szrecvmsg, 256);

sprintf (szoutmsg, "receive MSG: % s", szrecvmsg);
adlg-> getdlgitemtext (idc_edit_log, strtext );
strtext + = szoutmsg;
adlg-> setdlgitemtext (idc_edit_log, strtext );
// send content to the client
serversocket. send ("have receive the MSG", 50);

// Close
Serversocket. Close ();
}

}

// Close
Asocket. Close ();
Serversocket. Close ();

Adlg-> getdlgitemtext (idc_edit_log, strtext );

Strtext + = "have close! ";

Adlg-> setdlgitemtext (idc_edit_log, strtext );

Return 0;
}


// bind the port
If (! Asocket. BIND (nport)
... {
char szerror [256] =... {0 };
sprintf (szerror, "bind faild: % d", getlasterror ();
afxmessagebox (szerror );
return 1;
}< br>
3) server code under the SDK

// Subthread Functions
Unsigned int startserver (lpvoid lparam)
...{

// Initialize Winsock. afxsocketinit () also encapsulates these statements. However, afxsocketinit () does more than this.

Wsadata;

// Winsock version. We recommend that you use 1.1 for better compatibility.
Word wversionrequested = makeword (1, 1 );
Int nresult = wsastartup (wversionrequested, & wsadata );
If (nresult! = 0)
...{
Return 1;
}

//-----------------------------------------------------

M_exit = false;

Cserverdlg * adlg = (cserverdlg *) lparam;

Cstring strport;
 
Adlg-> getdlgitemtext (idc_edit_port, strport );
 
Uint nport = atoi (strport );
 
// Socket ------------------------------------------------

// Interface object
Socket asocket, serversocket;

// Addressing-Related Structure
Sockaddr_in serversockaddr;
Memset (& serversockaddr, 0, sizeof (serversockaddr ));

Asocket = socket (af_inet, sock_stream, ipproto_tcp );

If (asocket = invalid_socket)
... {
char szerror [256] =... {0 };
sprintf (szerror, "Create faild: % d", getlasterror ();
afxmessagebox (szerror );
return 1;
}

// Note that this is very important. Whether the value is correct or not determines whether the port can be released normally after scoket is disabled.
Bool boptval = true;
Int boptlen = sizeof (bool );

// Set the socket option. sol_socket and so_reuseaddr are used together, and the following parameters are as follows,
After scoket is disabled, the port can be released normally.
Setsockopt (asocket, sol_socket, so_reuseaddr, (char *) & boptval, boptlen );
 
// Addressing-Related Structure
Sockaddr_in asockaddr;
Memset (& asockaddr, 0, sizeof (asockaddr ));

Asockaddr. sin_family = af_inet;

Asockaddr. sin_addr.s_addr = htonl (inaddr_any );
 
Asockaddr. sin_port = htons (u_short) nport );
 
// Binding: Pay attention to parameter type conversion
If (BIND (asocket, (sockaddr *) & asockaddr, sizeof (asockaddr) = socket_error)
...{
Char szerror [256] =... {0 };

Sprintf (szerror, "bind faild: % d", getlasterror ());

Afxmessagebox (szerror );

Return 1;
}

 
// Listen
If (Listen (asocket, 10) = socket_error)
...{
Char szerror [256] =... {0 };

Sprintf (szerror, "Listen faild: % d", getlasterror ());

Afxmessagebox (szerror );

Return 1;
}
 
Cstring strtext;

Adlg-> getdlgitemtext (idc_edit_log, strtext );

Strtext + = "Server start! ";

Adlg-> setdlgitemtext (idc_edit_log, strtext );

While (! M_exit)
...{
// Receive external connections, non-blocking
Serversocket = accept (asocket, (sockaddr *) & serversockaddr, 0 );

If (serversocket = invalid_socket)
...{
Continue;
}
Else
...{
Char szrecvmsg [256] =... {0 };
Char szoutmsg [256] =... {0 };

// Receive client content: Blocking
Recv (serversocket, szrecvmsg, 256, 0 );

Sprintf (szoutmsg, "receive MSG: % s", szrecvmsg );

Adlg-> getdlgitemtext (idc_edit_log, strtext );

Strtext + = szoutmsg;

Adlg-> setdlgitemtext (idc_edit_log, strtext );

// Send content to the client
Send (serversocket, "have receive the MSG", 50, 0 );

// Close
Closesocket (serversocket );
}

}
 
// Close
Closesocket (asocket );
Closesocket (serversocket );

Adlg-> getdlgitemtext (idc_edit_log, strtext );
 
Strtext + = "have close! ";

Adlg-> setdlgitemtext (idc_edit_log, strtext );

// After you use the Winsock interface, you need to call the following function to release the resources occupied by it.
Wsacleanup ();

Return 0;
}

3. Summary
1) MFC programming is indeed relatively simple, with less code and easy to manage. The only bad thing is that a lot of details are not easily identified on the materials, and the associations are very close. Like the afxsocketinit () function, the implementation of functions contains many classes that are not easy to understand and records a lot of environment information, such as the created thread, in this way, after the main thread calls, the sub-thread will fail to call and execute the csocket operation. In addition, the design of some interfaces is very bizarre. For example, the csocket: Create interface is implemented with csocket: bind, which is very difficult to detect. In addition, the descriptions of csocket: bind on msdn clearly indicate that the csocket: bind operation must be executed.

2) SDK programming is easier to understand the call sequence of functions and the code structure, saving the time needed to encapsulate the components that do not know anything in MFC, making the code process easy to control. However, from the above examples, it is obvious that it is not so easy to understand. There are not only a lot of strange structures (Microsoft's naming has always been like this, and there is no cloud), and the function correlation is too tight, it is not easy for beginners to get familiar with it at once, code management is very troublesome for developers.

 

Reprinted please indicate the source: http://blog.csdn.net/yejiansnake/archive/2008/03/13/2175778.aspx

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.