TCP is the transmission control protocol. Unlike UDP, UDP is a reliable transmission protocol for connections and data streams. That is, he can make the data on a computer error-free to other computers on the network, so when the drug transmits a large amount of data, we choose TCP protocol.
The TCP program uses the Client/Server mode. In QT, The qtcpsocket class is provided to write client programs and the qtcpserver class is used to write server programs. We listen on the port on the server. Once the client connection request is found, the newconnection () signal will be sent. We can associate this signal with our own slot function, send data. On the client side, a readyread () signal is sent when data arrives. We can associate this signal to accept the data. In fact, the most difficult thing to understand in a program is the program's sending and receiving.
I. Server Side
In the server-side program, we listen to a port of the local host. Here we use 6666, and then associate the newconnection () signal with the self-written sendmessage () slot function. That is to say, once a client connection request is sent, the sendmessage () function is executed. In this function, a simple string is sent.
1. Create a New qt4guiapplication named "tcpserver"
Select the qtnetwork module and base classSelect qwidget. (Note: if some QT creator versions do not add a module, we need to add a line of code in the project file tcpserver. Pro: QT + = Network)
2. We add a label in the design area of the widget. UI and change its objectname to statuslabel to display some status information. As follows:
3. Make the following changes in the widget. h file.
Add a header file: # include <qtnetwork>
Add private object: qtcpserver * tcpserver;
Add a private slot function:
Private slots:
Voidsendmessage ();
4. Make changes in the widget. cpp file.
Add code to its constructor:
Tcpserver = newqtcpserver (this );
If (! Tcpserver-> listen (qhostaddress: localhost, 6666 ))
{// Listen to port 6666 of the local host. If an error occurs, the error message is output and disabled.
Qdebug () <tcpserver-> errorstring ();
Close ();
}
Connect (tcpserver, signal (newconnection (), this, slot (sendmessage ()));
// Connection signal and corresponding slot function
We use the listen () function of tcpserver to listen in the constructor, and then associate newconnection () with our own sendmessage () function.
The sendmessage () function is implemented below.
Voidwidget: sendmessage ()
{
Qbytearray block; // used to store the data to be sent
Qdatastream out (& Block, qiodevice: writeonly );
// Write data using data streams
Out. setversion (qdatastream: qt_4_6 );
// Set the data stream version. The client and server versions must be the same.
Out <(quint16) 0;
Out <tr ("Hello TCP !!!");
Out. Device ()-> seek (0 );
Out <(quint16) (Block. Size ()-sizeof (quint16 ));
Qtcpsocket * clientconnection = tcpserver-> nextpendingconnection ();
// Obtain the sub-socket of the established connection
Connect (clientconnection, signal (disconnected (), clientconnection,
Slot (deletelater ()));
Clientconnection-> write (Block );
Clientconnection-> disconnectfromhost ();
UI-> statuslabel-> settext ("Send message successful !!!");
// After the data is sent successfully, a prompt is displayed.
}
This is the data sending function. We mainly introduce two points:
(1) to ensure that the client can receive the complete file, we write the full file size information at the beginning of the data stream, in this way, the client can determine whether to accept the complete file based on the size information. On the server side, we must first send the actual file size information when sending data. However, the file size is unpredictable at the beginning, so we first used out <(quint16) 0; added a quint16 size space at the beginning of the block, that is, two bytes of space, it is used for storing the file size information. Then out <tr ("hellotcp !!!"); Enter the actual file, which is a string. After the file is input, we use out. device ()-> seek (0); return to the beginning of the block, and add the actual file size information, that is, the subsequent code, which is the actual file size: out <(quint16) (Block. size ()-sizeof (quint16 ));
(2) on the server side, we can use the nextpendingconnection () function of the tcpserver to obtain the TCP socket of the established connection and use it to send data and perform other operations. For example, we associate the disconnected () signal with the elater () slot function, and then we send data
Clientconnection-> write (Block );
Then there is clientconnection-> disconnectfromhost (); it indicates that the connection will be disconnected when sending is complete, then the disconnected () signal will be sent, and the deletelater () is called at last () the function ensures that the clientconnection of the socket is deleted after the connection is closed.
5. Then the server program is completed. Run the program first.
Ii. Client.
We send a connection request to the server in the client program, and receive the data sent by the server when the connection is successful.
1. Create a qt4 GUI application named "tcpclient", select the qtnetwork module, and select qwidget as the base class.
2. We add several labels, two line edits, and one button push button to the widget. UI.
The objectname of line edit after "host" is hostlineedit, and "port number" is portlineedit.
The objectname of the "received information" label is messagelabel.
3. Make changes in the widget. h file.
Add a header file: # include <qtnetwork>
Add private variable:
Qtcpsocket * tcpsocket;
Qstringmessage; // stores the string received from the server
Quint16blocksize; // file size information
Add a private slot function:
Private slots:
Void newconnect (); // connect to the server
Void readmessage (); // receives data
Voiddisplayerror (q1_actsocket: socketerror); // Display Error
4. Make changes in the widget. cpp file.
(1) Add code to the constructor:
Tcpsocket = newqtcpsocket (this );
Connect (tcpsocket, signal (readyread (), this, slot (readmessage ()));
Connect (tcpsocket, signal (error (q1_actsocket: socketerror )),
This, slot (displayerror (q1_actsocket: socketerror )));
The two signals of tcpsocket are associated here. When data arrives, the readyread () signal is sent. we execute the readmessage () function to read data. When an error occurs, an error () signal is sent. Execute the displayerror () slot function.
(2) Implement the newconnect () function.
Voidwidget: newconnect ()
{
Blocksize = 0; // initialize it to 0
Tcpsocket-> abort (); // cancel an existing connection
Tcpsocket-> connecttohost (ui-> hostlineedit-> text (),
UI-> portlineedit-> text (). toint ());
// Connect to the host. Obtain the host address and port number from the interface.
}
This function is used to connect to the server. Next, you can call this function by clicking the event slot function in the "Connect" button.
(3) Implement the readmessage () function.
Voidwidget: readmessage ()
{
Qdatastream in (tcpsocket );
In. setversion (qdatastream: qt_4_6 );
// Set the data stream version, which must be the same as that on the server.
If (blocksize = 0) // if it is the first time to receive data
{
// Determine whether the received data has two bytes, that is, the file size information.
// If yes, save it to the blocksize variable. If no, return and continue receiving data.
If (tcpsocket-> bytesavailable () <(INT) sizeof (quint16) return;
In> blocksize;
}
If (tcpsocket-> bytesavailable () <blocksize) return;
// If no data is obtained, return and continue receiving data
In> message;
// Store the received data in the Variable
UI-> messagelabel-> settext (Message );
// Display the received data
}
This function is used to receive data. It corresponds to the sending function on the server. First, we need to obtain the file size information, and then determine whether to receive the complete file based on the file size.
(4) Implement the displayerror () function.
Void Widget: displayerror (q1_actsocket: socketerror)
{
Qdebug () <tcpsocket-> errorstring (); // output error message
}
Here, the output of error messages is simply implemented.
(5) In the widget. UI, click the event slot function of the Connect button and change it as follows.
Voidwidget: on_pushbutton_clicked () // connection button
{
Newconnect (); // request a connection
}
The newconnect () function is called directly.
5. run the program, run the server program at the same time, enter "localhost" after "host", enter "6666" after "port number", and click "Connect". The effect is as follows.
We can see that we have correctly received the data. Because the server and client run on the same machine, I entered "host" as "localhost" here. If you run on different machines, you must enter the correct IP address after "host.
Here, we have completed the simplest TCP application. In the next section, we will expand it to implement arbitrary file transmission.
Qt network programming --- TCP (1)