Network programming socket UDP (1)

Get to know
the IP address and port number 1.
IP address There are two versions of IP address, IPv4 and IPv6. The IPv4 version occupies four bytes and 32 bits; the IPv6 version occupies 64 bytes and 128 bits, and most of the In this case, the IPv4 version is used by default. The IP data header contains two IP addresses, the source IP address and the destination IP address, where the source IP address indicates which host the data is sent from, and the destination IP indicates which host the data is sent to. But only the IP address will not work. We just forward the data to another host, and we don’t know which process to send the data to for parsing. At this time, we introduce the port number.
2. Port number Port number is a transport layer protocol.
The port number occupies two bytes, a 16-bit integer
. Port number is used to identify a unique process and tell the operating system to which process the currently received data needs to be delivered To handle
a port number can only be occupied by one process
3. The relationship between IP address and port number
IP address represents the only host among many hosts on the Internet, and
port number represents the only process among many processes in the host
IP address+ The port number can identify a process on a host
4. The relationship between the port number and the process ID The
process ID is used to uniquely identify a process, and the port number is only used to bind a process.
A process can be bound to multiple port numbers, but one port number cannot be bound by multiple processes. The understanding of
source port number and destination port number
means that the connection between a process in one host and a process in another host is Communication between
them They indicate who sent the data and who to send it to.
Sockets are used to represent communication between two processes, represented by IP address + port number
Recognize
the characteristics of TCP and UDP TCP: transport layer protocol, connection, reliable transmission, byte stream-oriented (that is, one byte can be used) One byte sent)
Features of UDP: transport layer protocol, connectionless, unreliable transmission, datagram-oriented (that is, receipts cannot be taken in bytes, all data packets must be taken at once)
network bytes The multi-byte data in the sequence
memory is divided into big and small ends relative to the memory address, the multi-byte data in the disk file is also divided into big and small ends relative to the offset address in the file, and the network data stream is also divided into big and small ends. , let's understand the address of the network data stream
1. The sending host usually sends the data in the buffer in the order of memory addresses from low to high.
2. The receiving host stores the bytes received on the network in the buffer in turn, and also 3. Therefore, the address of the network data stream is stipulated: the data sent first is the low
address, and the data sent later is the high address.
4. The TCP/IP protocol stipulates that the network data stream should use big-endian bytes, that is, low-address high-byte 5. The little-endian host must be converted to big
-endian before it can send data
to .
End storage: the high byte of the data is stored in the low address of the memory
Small segment storage: the high byte of the data is stored in the high address of the memory
write picture description here
In order to make the network portable, the following functions can be called to do the network byte order and host word transition between stanzas

#include <arpa/inet.h>
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
//前两组接口表示主机向网络中发送数据,将主机序转化为网络序
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);
//后两组表示网络接受主机发送的数据,将网络序转换成主机序
在不需要进行转换的情况下,这些函数不做任何处理直接返回

Socket programming
1. What is API?
API (Application Programming Interface, application programming interface) is some predefined functions, the purpose is to provide applications and developers with the ability to access a set of routines based on a certain software or hardware, and No need to access the source code, or understand the details of the inner workings.
2. Understand the sockaddr structure is
used to store an internet protocol (IP) address on a computer participating in (IP) Windows socket communication. In order to unify the representation method of the address structure, unify the interface functions, so that different address structures can be called by functions such as bind(), connect(), recvfrom(), and sendto(). But in general programming, this data structure is not directly operated, but another equivalent data structure sockaddr_in is used. This is because the Microsoft TCP/IP socket developer's toolbox only supports the internet address field, and each part of the actual padding field follows the sockaddr_in data structure, both of which are 16 bytes in size, so you can switch.
sockaddr structure

struct sockaddr {
  unsigned short sa_family; /* address family, AF_xxx */
  char sa_data[14]; /* 14 bytes of protocol address */
  };

Description:
sa_family: is a 2-byte address family, generally in the form of "AF_xxx", and its values ​​include three types: AF_INET, AF_INET6 and AF_UNSPEC.
If AF_INET is specified, the function cannot return any IPV6-related address information; if only AF_INET6 is specified, it cannot return any IPV4 address information.
AF_UNSPEC means that the function returns an address suitable for the specified host name and service name and suitable for any protocol family. If a host has both an AAAA record (IPV6) address and an A record (IPV4) address, the AAAA record will be returned as a sockaddr_in6 structure, and the A record will be returned as a sockaddr_in structure.
Usually , the AF_INET
sockaddr_in structure is used.

struct sockaddr_in {
  short int sin_family; /* Address family */
  unsigned short int sin_port; /* Port number */
  struct in_addr sin_addr; /* Internet address */
  unsigned char sin_zero[8]; /* Same size as struct sockaddr */
  };

sin_family: refers to the protocol family, which can only be AF_INET in socket programming
  sin_port: stores the port number (using network byte order)
  sin_addr: stores the IP address, using the in_addr data structure
  sin_zero: is to allow two data structures of sockaddr and sockaddr_in Null bytes reserved for keeping the same size.
  Although the interface of the socket API is sockaddr, when we are actually programming based on IPV4, the data structure used is sockaddr_in; this structure mainly includes 16-bit address type, 16-bit port number, 32-bit IP address
in_addr structure
 

typedef struct in_addr {
  union {
  struct{ unsigned char s_b1,s_b2, s_b3,s_b4;} S_un_b;
  struct{ unsigned short s_w1, s_w2;} S_un_w;
  unsigned long S_addr;
  } S_un;
  } IN_ADDR;

Explaining the meaning of in_addr, it is obvious that it is a common body that stores IP addresses. There are three expressions:
the first one uses four bytes to represent the four numbers of the IP address; the
second one uses two double bytes to represent IP address;
the third uses a long integer to represent the IP address.
One of the easiest ways to assign a value to in_addr is to use the inet_addr function, which can convert a string assignment representing an IP address to an in_addr type, such as addrto.sin_addr.s_addr=inet_addr("192.168.0.2");
its inverse function is inet_ntoa, can convert an in_addr type to a string.
 

**·**IPV4 and IPV6 address formats are defined in netinet.h, IPV4 address is represented by sockaddr_in structure, including 16-bit address type, 16-bit port number, 32-bit IP address
**·**IPV4, IPV6 The address types are defined as constants AF_INET and AF_INET6, so as long as the first address of a certain sockaddr structure is obtained, the content of the structure can be determined according to the address type field without knowing the specific type of sockaddr structure.
· The socket API can be represented by the struct sockaddr* type, and it needs to be converted into sockaddr_in when used. The advantage of this is the versatility of the program. It can accept IPV4, IPV6, and various types of sockaddr structure pointers of UNIX Domain Socket as Parameter  
3, socket common API

 //创建socket文件描述符,该函数返回一个文件描述符,(TCP/UDP客户端+服务器)
 int socket(int domain, int type, int protocol);
 //绑定端口号(TCP/UDP服务器)
 int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
 //接受请求(TCP服务器)
int accept(int sockfd, struct sockaddr *addr, socklen* addrlen);
//建立连接(TCP客户端)
int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

Implement the short answer version of UDP
server.c

#include<stdio.h>
#include<arpa/inet.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include<netinet/in.h>
#include<error.h>
#include<unistd.h>
#include<string.h>
struct sockaddr_in local;
local.sin_family=AF_INET;
local.sin_port=htons(atoi(argv[2]));
local.sin_addr.s_addr=inet_addr(argv[1]);//sin_addr是一个结构体
int main(int argc,char* argv[])
{
  if(argc!=3)
  {
    printf("Usage: %s [ip] [port]",argv[1]);
    return 3;
  }
  int sock=socket(AF_INET,SOCK_DGRAM,0);//创建一个端口号
  if(sock<0)
  {
    perror("socket");
    return 2;
  }
 if(bind(sock,(struct sockaddr*)&local,sizeof(local))<0)//绑定端口号
 {
 perror("bind");
 return 3;
 }
 //绑定端口号成功,定义一个缓冲区开始接收数据
 char buf[1024];
 struct sockaddr_in client;
 while(1)
 {
   socklen_t len=sizeof(client);
   ssize_t s=recvfrom(sock,buf,sizeof(buf-1),0,(struct sockaddr *)&client,&len);
   if(s>0)
   {
     printf("[%s:%d]:%s\n",inet_ntoa(client.sin_addr),\
         ntohs(client.sin_port,buf));
     sendto(sock,buf,strlen(buf),0,(struct sockaddr*)&client,\
         sizeof(client));
   }
 }
close(socket);
}
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<socket.h>
int main(int argc,int agrv[])
{
 if(argc!=3)
 {
 printf("Usage %s [ip] [port]",argv[1]);
 return 1
 }
 int sock=socket(AF_INET,SOCK_DGRAM,0);
 if(sock<0)
 {
   perror("socket");
   return 2
 }
 struct sockaddr_in server;
 server.sin_family=AF_INET;
 server.sin_port=htons(argv[2]);
 server.sin_addr.s_addr(argv[1]);
 char buf[1024];
 struct sockaddr_in peer;
 while(1)
 {
 socklen_t len=sizeof(peer);
 printf("please enter #");
 fflush(stdout);
 ssize_t s=read(0,buf,sizeof(buf)-1);
 if(s>0)
 {
 buf[s-1]=0;
 sendto(sock,buf,strlen(buf),(struct sockaddr*)&server,sizeof(peer));
 ssize_t s=recvfrom(sock,buf,sizeof(buf-1),0,(struct sockaddr*)&peer,&len);
   if(s>0)
   {
     buf[s]=0;
     printf("server echo # %s\n",buf);
   }
  }
 }
}

The parameters of socket use SOCK_DGRAM to represent UDP;
use sendto() and recvfrom() to receive and send data Functions
related to
address conversion String to in_addr

       int inet_aton(const char *cp, struct in_addr *inp);
       //将字符串转化为IP地址

       in_addr_t inet_addr(const char *cp);

       in_addr_t inet_network(const char *cp);

       char *inet_ntoa(struct in_addr in);
       //将四进制转化为点分十进制,inet_ntoa这个函数把返回结果放到了静态存储区,不需要手动进行释放,这个函数如果被多次调用,之前调用的结果会被覆盖。在Centos  6.5版本下是不可重入的。

       struct in_addr inet_makeaddr(int net, int host);

       in_addr_t inet_lnaof(struct in_addr in);

       in_addr_t inet_netof(struct in_addr in);

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326440375&siteId=291194637