Network Programming
1. TCP and UDP comparisons
TCP is connection-oriented, and each interaction process establishes a streaming socket, and the server waits for the client to submit a connection request to it. Once the client request is accepted, a new socket descriptor is returned immediately. This descriptor is used to call the data transfer function and the client to send and receive.
UDP is for connectionless, the two sides set up a datagram socket, the server and the client in the transmission of the data without the need to connect the application and establishment, you can send messages to each other at any time.
Tcp
Advantages: Reliable, stable
Disadvantages: Slow speed, low efficiency, high utilization of system resources, easy to be attacked.
Suitable scenario: Network communication quality requirements high (reliable, stable)
Udp
Advantage: fast, slightly safer than TCP
Disadvantages: unreliable, unstable
Applicable occasions: Network communication quality requirements are not high, fast. 2. Socket Sticky Package Problem
when to think about sticky issues
1: If you use TCP to send data each time, you establish a connection with each other, and then the two sides send out a piece of data, then close the connection, so there will be no sticky problem (because there is only one package structure, similar to the HTTP protocol). Close the connection primarily to both sides send a close connection (refer to the TCP shutdown protocol). Such as: a need to send a string to B, then A and B to establish a connection, and then send both sides of the default good protocol word Furu "Hello give me sth abour yourself", and then B received the message, the buffer data received, and then closed the connection, so the sticky problem does not take into account Because we all know is to send a paragraph of characters;
2: If the sending data has no structure, such as file transmission, so that the sender just send, the receiver only receive storage on OK, also do not consider sticky package;
3: If the two sides establish a connection, need to send a period of time after the connection of different structural data, such as after the connection, there are several structures:
1) "Hellogive me sth abour Yourself"
2) "Don ' tgive me sth abour Yourself"
That way, if the sender sends this two packets continuously, the receiver may be "Hello give me sth abour yourselfdon ' t give me sth abouryourself" so that the receiver will be silly, exactly what to do. Do not know, because the protocol does not prescribe such a strange string, so to deal with it subcontracting, how to divide also need to organize a better package structure, so generally may be in the header plus a data length of the package, to ensure that receive.
Why the Sticky pack appears:
In a convective transmission, UDP does not appear to be sticky because it has message protection boundaries.
1 The sender need wait buffer full before sending out, causing the sticky package
2 receiver does not receive buffer packets in time, causing multiple packets to receive
Solution:
In order to avoid the sticky phenomenon, the following measures can be taken:
One is for the sender caused by the sticky phenomenon, the user can be programmed to avoid, TCP provides the mandatory data transfer immediately operation instructions PUSH,TCP Software received the operation instructions, immediately send this paragraph of data out, without waiting to send buffer full;
Second, for the receiver caused by the sticky package, it can be optimized program design, streamline the process of receiving the workload, improve the priority of receiving process, and so on, so that it received data in time, so as to avoid the phenomenon of sticky packets;
Third, by the receiver control, a packet of data according to the structure of the field, artificial control to receive several times, and then merged, through this means to avoid sticky packets.
The three measures mentioned above have their drawbacks.
The first programming setting method avoids the sticky packets caused by the sender, but it turns off the optimization algorithm, reduces the efficiency of the network transmission, and affects the performance of the application, which is generally not recommended.
The second method can only reduce the likelihood of sticking, but can not completely avoid the sticky packet, when the sending frequency is high, or because the network burst may make a time packet to reach the receiver faster, the receiver is still likely to be too late to receive, resulting in sticky packets.
The third method avoids the sticky package, but the application is less efficient and unsuitable for real-time applications.
A more concise version:
Fixed bag length
Baulinga \ r \ n
The length of the package body of Baotou
Online saying:
One of the most preferred approach is to give a frame of data frame head frame tail, and then the receiver constantly accept and cache the received data, according to the frame end of the frame to separate a complete data, and then separate the fields to get data.
If a package is wrong, how to keep recovering.
When sending a message, each message length is specified when it is programmed. If there is a problem with the packet received, we can continue to reply to the original packet by the length of the message. 3. TCP Example
Service side:
#include <stdio.h> #include <WinSock2.h> #pragma comment (lib, "Ws2_32.lib") int _tmain (int argc, _tchar* argv[]) { Wsadata Wsadata; int port = 5099; Char buf[] = "Server: Welcome to login ... \ n"; Load sockets if (WSAStartup (Makeword (2, 2), &wsadata)!= 0) { printf ("Load socket failed:%d......\n", WSAGetLastError ()); return 1; } Socket () Socket SOCKSRV = socket (af_inet, sock_stream, 0); Initializing IP and port information Sockaddr_in addrsrv; addrsrv.sin_family = af_inet; Addrsrv.sin_port = htons (port); More than 1024 of the port number Addrsrv.sin_addr. S_un. S_ADDR = htonl (Inaddr_any); Bind () if (Bind (Socksrv, (lpsockaddr) &addrsrv, sizeof (sockaddr_in)) = = Socket_error) { printf ("Socket bind failed:%d......\n", WSAGetLastError ()); return 1; } Listen () if (listen (socksrv) = = Socket_error) { printf ("Socket Listener failure:%d......\n", WSAGetLastError ()); return 1; } Client Information Sockaddr_in addrclient; int len = sizeof (SOCKADDR); Start listening. printf ("Server-side startup successful ...") Start listening ... \ n "); while (1) { Waiting for customer requests to arrive SOCKET Sockconn = Accept (Socksrv, (SOCKADDR *) &addrclient, &len); if (Sockconn = = Socket_error) { printf ("Establish Connection failed:%d......\n", WSAGetLastError ()); Break } printf ("Establish a connection with the client ...) Ip:[%s]\n ", Inet_ntoa (ADDRCLIENT.SIN_ADDR)); Send data if (Send (Sockconn, buf, sizeof (BUF), 0) = = socket_error) { printf ("Send data failed ... \ n"); Break } Char recvbuf[100]; memset (recvbuf, 0, sizeof (RECVBUF)); Receive data Recv (Sockconn, Recvbuf, sizeof (RECVBUF), 0); printf ("Received data:%s\n", recvbuf); Closesocket (Sockconn); } Close socket Closesocket (SOCKSRV); WSACleanup (); System ("pause"); return 0; } |
Client:
#include <stdio.h> #include <WinSock2.h> #pragma comment (lib, "Ws2_32.lib") int _tmain (int argc, _tchar* argv[]) { Wsadata Wsadata; int port = 5099; Char buff[1024]; memset (buff, 0, sizeof (buff)); Load sockets if (WSAStartup (Makeword (2, 2), &wsadata)!= 0) { printf ("Load socket failed:%d......\n", WSAGetLastError ()); return 1; } Initializing IP and port information Sockaddr_in addrsrv; addrsrv.sin_family = af_inet; Addrsrv.sin_port = htons (port); Addrsrv.sin_addr. S_un. S_ADDR = inet_addr ("127.0.0.1"); Socket () Socket sockclient = socket (af_inet, sock_stream, 0); if (Socket_error = = sockclient) { printf ("Create Socket failed:%d......\n", WSAGetLastError ()); return 1; } Making a connection request to the server if (Connect (sockclient, (struct sockaddr*) &addrsrv, sizeof (addrsrv)) = = Invalid_socket) { printf ("Connect Server failed:%d......\n", WSAGetLastError ()); return 1; } Else { Receive data recv (sockclient, buff, sizeof (buff), 0); printf ("Received data:%s\n", buff); Send data Char buf[] = "Client: Request login ..."; Send (Sockclient, buf, sizeof (BUF), 0); } Close socket Closesocket (sockclient); WSACleanup (); return 0; } |
Old function Workaround:
4. UDP Example
Service side (receiver):
UDPReceiverTest.cpp: Defines the entry point for a console application. // #include "stdafx.h" #include <stdio.h> #include <WinSock2.h> #pragma comment (lib, "Ws2_32.lib") int _tmain (int argc, _tchar* argv[]) { Wsadata Wsadata; int port = 5099; Load sockets if (WSAStartup (Makeword (2, 2), &wsadata)!= 0) { printf ("Load socket failed:%d......\n", WSAGetLastError ()); return 1; } Initializing IP and port information Sockaddr_in addrsrv; addrsrv.sin_family = af_inet; Addrsrv.sin_port = htons (port); Addrsrv.sin_addr. S_un. S_ADDR = htonl (Inaddr_any); Socket () Socket sockclient = socket (af_inet,sock_dgram, 0); if (Socket_error = = sockclient) { printf ("Create Socket failed:%d......\n", WSAGetLastError ()); return 1; } Bind () if (Bind (Sockclient, (lpsockaddr) &addrsrv, sizeof (sockaddr_in)) = = Socket_error) { printf ("Socket bind failed:%d......\n", WSAGetLastError ()); return 1; } Sockaddr_in addrclnt; int nlen = sizeof (SOCKADDR); News Char szmsg[1024]; memset (szmsg, 0, sizeof (szmsg)); Waiting for customer requests to arrive printf ("Server-side startup successful ...") Wait for customer to send data ... \ n "); while (1) { Receive data if (Socket_error!= recvfrom (sockclient, szmsg, sizeof (szmsg), 0, (sockaddr*) &addrclnt, &nlen)) { printf ("Sender:%s\n", szmsg); Char szsrvmsg[] = "Receive ..."; Send data SendTo (sockclient, szsrvmsg, sizeof (SZSRVMSG), 0, (sockaddr*) &addrclnt, Nlen); } } The following code does not perform the wireless loop above Close socket Closesocket (sockclient); WSACleanup (); return 0; } |
Client:
UDPSenderTest.cpp: Defines the entry point for a console application. // #include "stdafx.h" #include <stdio.h> #include <WinSock2.h> #pragma comment (lib, "Ws2_32.lib") int _tmain (int argc, _tchar* argv[]) { Wsadata Wsadata; int port = 5099; Load sockets if (WSAStartup (Makeword (2, 2), &wsadata)!= 0) { printf ("Load socket failed:%d......\n", WSAGetLastError ()); return 1; } Socket () Socket sockclient = socket (af_inet, SOCK_DGRAM, 0); if (Socket_error = = sockclient) { printf ("Create Socket failed:%d......\n", WSAGetLastError ()); return 1; } Initializing IP and port information Sockaddr_in addrsrv; addrsrv.sin_family = af_inet; Addrsrv.sin_port = htons (port); Addrsrv.sin_addr. S_un. S_ADDR = inet_addr ("127.0.0.1"); int nlen = sizeof (SOCKADDR); Send data Char szmsg[1024]; memset (szmsg, 0, sizeof (szmsg)); SendTo (sockclient, szmsg, sizeof (szmsg), 0, (sockaddr*) &addrsrv, Nlen); Send data while (1) { Initializing data Char szmsg[1024]; memset (szmsg, 0, sizeof (szmsg)); printf (enter Q to exit): "Enter the data to be sent." scanf ("%s", &szmsg); Exit loop if (!strcmp (szmsg, "q") | | |!strcmp (szmsg, "Q")) { Break } Send data SendTo (sockclient, szmsg, sizeof (szmsg), 0, (sockaddr*) &addrsrv, Nlen); Empty cache memset (szmsg, 0, sizeof (szmsg)); // |