Socket programming considerations:
1. Connection timeout
Not recommended
M_socket = new socket (fm_ipaddr, fm_port );
M_socket.setsotimeout (180000); // The data read timeout value is set to 3 MB.
In the preceding method, when the other port is dropped, the client waits for the connection and does not throw an exception. So there is no timeout at all.
Recommended Syntax:
M_socket = new socket ();
M_socket.setsotimeout (180000); // The data read timeout value is set to 3 MB.
M_socket.connect (New inetsocketaddress (fm_ipaddr, fm_port), 2000); // set connection establishment timeout
2. When performing stream operations, it is best to add the following judgment:
M_socket.sendurgentdata (0xff); // checks whether the network is disconnected.
3. Whether to disable the output stream and input stream
For the same socket, if the output stream is disabled, the socket associated with the output stream is also disabled. Therefore, you do not need to close the stream. Simply close the socket. The above has proved feasible.
This article from the csdn blog, reproduced please indicate the source: http://blog.csdn.net/e3002/archive/2009/01/17/3806984.aspx
Socket programming considerations
UDP ----- socket port number
The client's socket seldom calls BIND () to specify the socket port number. Instead, the operating system is usually assigned a port number automatically.
The socket Port Number of the TCP client is automatically allocated after connect () is called.
The socket Port Number of the UDP client is automatically allocated after sendto () is called for the first time. If the UDP port is automatically allocated, the system will not change the port number. If the udp ip address is also automatically allocated, the source IP address may be changed every time the sendto () system is called.
Weak end system vs strong end system
The network interface will receive all data packets consistent with the local IP address, called weak end system.
The network interface only receives all data packets that are the same as the IP address of this interface, which is called strong end system.
The difference is that a multihome host has multiple network interfaces, so the strong end system filtering check will be more powerful.
The data sending Address of UDP is inconsistent with the Data Receiving address.
A udp client is sent to the server. If the network interface used by the server for receiving has multiple IP addresses, the server automatically selects a primary IP address to send the response to the client. The primary IP address may be different from the IP address sent by the client.
If the client determines whether the server sends a response based on the IP address of the received response, an error may occur. The solution is to modify the client. The IP address is no longer used to determine whether a data packet is sent by a server. Instead, the IP address is determined based on the domain name obtained by DNS. The disadvantage is that the system must have a Domain Name Server, and domain name query will affect the efficiency. One way is that the server does not use wildcard to bind a socket, but to bind a socket for each IP address. The disadvantage is that the system needs to restart the server if the IP address is changed dynamically, and the server must be added with select () Check for all sockets.
UDP ICMP
After sendto () is returned successfully, it means that the network interface of the host has enough Buffer Queue space to accommodate the data to be sent. If the receiving end sends ICMP messages back, it is unknown to the socket, unless UDP socket also calls connect () to change to connected UDP socket.
In Linux, the unconnected socket will also return an ICMP error, as long as so_bsdcompat socket option is not set.
The ICMP message is returned in the next read (). The error value is econnrefused.
Some System V systems have bugs and do not return ICMP Errors for connected socket.
Connected UDP socket vs unconnected UDP socket the UDP socket that calls the connect () function changes from unconnected UDP socket to connected UDP socket.
Connect () does not actually establish a connection, but connects the socket with a peer name.
The operation of the function connect () function is a local operation and does not involve the network.
The system searches for the network interface based on the destination address specified by the connect () function, and selects the primary IP address of the network interface as the local address.
Differences:
The connected socket calls send instead of sendto.
The connected socket calls Recv instead of recvfrom. Only when the destination address is the same as the address specified by the connect () function will it be received.
Problem: if the system determines a connection based on the IP address, it is also possible that the destination address for sending the command is different from the source address for receiving the response.
Answer: you only need to modify the server.
An ICMP error is returned.
When sending data, because you do not need to specify the destination IP address, less data is transferred between the user program and the kernel, so the efficiency is slightly higher.
Whether the connected UDP socket can call connect () is different from TCP. The connected socket can call connect () multiple times (). If the address family in the target address of Connect () is af_unspec, the connected socket will become unconnected socket. Eafnosupport may be returned, but it does not matter.
Example
// Test get peer name
# Include <string. h>
# Include <sys/socket. h>
# Include <netinet/in. h>
# Include <ARPA/inet. h>
# Include <sys/socket. h>
# Include <stdio. h>
# Include <stdlib. h>
# Include <errno. h>
# Define sure do {If (errno! = 0) {fprintf (stderr, "line % d: % s/n" ,__ line _, strerror (errno); exit (1 );}} while (0)
Int main (INT argc, char * argv [])
{
Int S;
Int C;
// Int on = 1;
Struct sockaddr_in ADDR;
Int Len = sizeof (ADDR );
Memset (& (ADDR), 0, Len );
S = socket (af_inet, sock_stream, 0 );
Sure;
ADDR. sin_family = af_inet;
ADDR. sin_port = htons (1996 );
ADDR. sin_addr.s_addr = inaddr_any;
BIND (S, (struct sockaddr *) & ADDR, Len );
Sure;
Listen (S, 4 );
Sure;
Memset (& (ADDR), 0, sizeof (ADDR ));
C = accept (S, (struct sockaddr *) & ADDR, & Len );
Sure;
Printf ("peer: % s: % d./N", inet_ntoa (ADDR. sin_addr), ntohs (ADDR. sin_port ));
Memset (& (ADDR), 0, sizeof (ADDR ));
Getpeername (C, (struct sockaddr *) & ADDR, & Len );
Sure;
Printf ("peer: % s: % d./N", inet_ntoa (ADDR. sin_addr), ntohs (ADDR. sin_port ));
Return 0;
}
Http://hi.baidu.com/iruler/blog/item/37696623dc53e84c92580723.html
Do you notice the details in socket programming?
Socket programming is often used in both Windows and Linux. However, the correct use of socket-related functions is critical, especially the processing details of individual functions. Unexpected situations may occur.
A few days ago, when I wrote a module using socket, I encountered a depressing situation for several days:
The accept function is not blocked !! The original statement is as follows:
Socket acceptsocket;
While (m_bstart)
{
Acceptsocket = socket_error;
While (acceptsocket = socket_error)
{
Acceptsocket = accept (m_socket, null, null );
}
// Process the access acceptsocket
}
It works normally. One day, my colleague asked, can I get the IP address and port used to access the socket? I did not hesitate to answer: "Of course you can." So I wrote the following code:
Socket acceptsocket;
// Store the address information of the connected Client
Struct sockaddr_in client_socket;
Int Len;
While (m_bstart)
{
Acceptsocket = socket_error;
While (acceptsocket = socket_error)
{
Acceptsocket = accept (m_socket, (struct sockaddr *) & client_socket, & Len );
}
// Process the access acceptsocket
}
The idea is that the IP address and port used to access the socket can be obtained. The IP address is stored in client_socket.sin_addr, and the port is stored in client_socket.sin_port.
Compile and run. CPU usage: 100% !! The access IP address and port cannot be obtained.
Why ?????
Check msdn as follows:
Accept
The accept function permits an incoming connection attempt on a socket.
Socket accept (
Socket s,
Struct sockaddr * ADDR,
Int * addrlen
);
Parameters
S
[In] descriptor that identifies a socket that has been placed in a listening state with the listen function. The connection is actually made with the socket that is returned by accept.
ADDR
[Out] Optional pointer to a buffer that matches es the address of the connecting entity, as known to the communications layer. the exact format of the ADDR parameter is determined by the address family that was established when the socket from the sockaddr structure was created.
Addrlen
[In, out] Optional pointer to an integer that contains the length of ADDR.
Do you see any problems ?? Let's take a closer look and think the code is correct !?
After several days of being depressed, I accidentally noticed the addrlen parameter description: [In, out]. In this case, have you noticed this ?? That is to say, the addrlen parameter of the accept function is both an input parameter and an output parameter. The key is to enter a parameter, that is, the value must be paid during use !! After understanding this, the problem will be changed. Change the above Len statement:
Int Len = sizeof (struct sockaddr_in );
Compile and run. Everything is OK! I am depressed for several days. Have you ever been depressed by such a problem ?? :) Http://blog.sina.com.cn/s/blog_46e73e770100067j.html
Socket and Multithreading
What should I pay attention to when using socket? What do I need to know about multithreading?
Exception Handling, especially socket exception handling, is more important, because the end connected to you will not receive your error notification. When both are multithreading, pay attention to the management of thread shared resource locks. It is recommended that each resource have only one writable synchronized object, and each operation on this resource must be performed through this object, which is not easy to forget and is more efficient. The socket should also note that a customer may connect to the server in two ways. In this case, the server is allowed or denied to be clear.
Note that multithreading is not recommended if multithreading is not required. Generally, multiple threads are required: Message loop, socket server listener, and other places that require endless loops.
Multithreading is often used in places where an endless loop is needed. Since it is an endless loop, this thread should pay attention to the priority. A small plug-in for Starcraft was previously done. If the priority is not set, it will be very slow to play Starcraft, set priority minus 1 to-1 (C ++, that is, lower than normal. In the server, you also need to pay attention to the priority of the listener. Generally, it should be lower. In addition, the socket should pay attention to security, which involves the best network security measures at each step. Encryption is required for the transmitted password. If you are using a hook-up program, do not destroy the original data of the process, whether it is multithreading or socket.
Socket requires pooled resources-multi-thread synchronization