天天看點

Linux Socket 程式設計相關函數struct sockaddr and struct sockaddr_insocket 函數bind函數listen函數accept函數connect函數

struct sockaddr

and

struct sockaddr_in

struct sockaddr

定義在<sys/socket.h>頭檔案中,原型如下

/* Structure describing a generic socket address.  */
struct sockaddr{
	//unsigned short int sa_family;
	//表明協定族,通常為:AF_INET (IPV4) AF_INET6(IPV6) 
	//PF_INET含義同AF_INET一樣
    __SOCKADDR_COMMON (sa_);	/* Common data: address family and length.  */
    //存放ip位址的字元形式如:0.0.0.0
    char sa_data[14];		/* Address data.  */
};
           

struct sockaddr_in

定義在<netinet/in.h>中,原型如下:

/* Internet address.  */
typedef uint32_t in_addr_t;
struct in_addr{
    in_addr_t s_addr;
};
/* Structure describing an Internet socket address.  */
struct sockaddr_in{
	//short  int  sin_family;
    __SOCKADDR_COMMON (sin_);
    in_port_t sin_port;			/* Port number.  */
    struct in_addr sin_addr;		/* Internet address.  */

    /* Pad to size of `struct sockaddr'.  */
    unsigned char sin_zero[sizeof (struct sockaddr) -
			   __SOCKADDR_COMMON_SIZE -
			   sizeof (in_port_t) -
			   sizeof (struct in_addr)];
 };
           

socket

函數

函數原型如下

/* Create a new socket of type TYPE in domain DOMAIN, using
  	 protocol PROTOCOL.  If PROTOCOL is zero, one is chosen automatically.
  	 Returns a file descriptor for the new socket, or -1 for errors.  */
	extern int socket (int __domain, int __type, int __protocol) __THROW;
           

參數含義如下:

__domain 指明通信域,如

PF_UNIUX

(unix域)

PF_INET

(IPV4)

PF_INET6

(IPv6)

__type 指明通信類型,最常用

SOCK_STREAM

(面向連結的可靠方式TCP),

SOCK_DGRAM

(非面向連結的非可靠方式UDP),

SOCK_STREAM

是資料流,一般都是TCP/IP協定的程式設計,

SOCK_DGRAM

是資料包,是udp協定網絡程式設計

__protocol指定需要使用的協定,可以是:

IPPROTO_TCP

IPPROTO_UDP

使用

則根據前兩個參數使用預設位址

NOTE

:建立成功則傳回一個檔案描述符,

-1

則建立失敗

bind

函數

函數原型如下:

/* Give the socket FD the local address ADDR (which is LEN bytes long).  */
extern int bind (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len)__THROW;
           

參數含義

__fd 調用

scoket()

函數建立成功的檔案描述符(file descriptor)

__addr 的類型其實是

struct sockaddr *

一個本地位址

__len 第二個參數的大小

使用例子

struct sockaddr_in addr;
    //建立socket,擷取一個socket描述符
    if ((listen_fd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
        fprintf(stderr, "%s(): cannot create socket", __FUNCTION__);
        return -1;
    }
    //設定server的位址同通信協定
    memset(&addr, 0, sizeof(struct sockaddr_in));
    //協定族: AF_INET AF_INET6 AF_LOCAL
    addr.sin_family = AF_INET;
    //取本地任意一個位址進行通信
    // uint32_t htonl(uint32_t hostlong) 将主機無符号長整型轉化為網絡位元組
    //INADDR_ANY=0.0.0.0
    addr.sin_addr.s_addr = htonl(INADDR_ANY);
    // uint16_t htons(uint16_t hostshort) 将hostshort 轉化為網絡位元組序
    //網絡位元組采用大端模式(big-ending),高位存放在低位址
    addr.sin_port = htons(PORT);
    if (bind(listen_fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) != 0) {
        fprintf(stderr, "%s(): bind() failed", __FUNCTION__);
        goto failed;
    }
           

listen

函數

函數原型如下:

/* Prepare to accept connections on socket FD.
   N connection requests will be queued before further requests are refused.
   Returns 0 on success, -1 for errors.  */
extern int listen (int __fd, int __n) __THROW;
           

參數含義

__fd 調用

scoket()

函數建立成功的檔案描述符(file descriptor)

__n 等待連接配接隊列的最大長度

NOTE

:傳回

代表成功

-1

代表失敗

accept

函數

函數原型如下:

/* Await a connection on socket FD.
   When a connection arrives, open a new socket to communicate with it,
   set *ADDR (which is *ADDR_LEN bytes long) to the address of the connecting
   peer and *ADDR_LEN to the address's actual length, and return the
   new socket's descriptor, or -1 for errors.

   This function is a cancellation point and therefore not marked with
   __THROW.  */
extern int accept (int __fd, __SOCKADDR_ARG __addr,socklen_t *__restrict __addr_len);

           

參數含義:

__fd 調用

scoket()

函數建立成功的檔案描述符(file descriptor)

__addr 的類型其實是

struct sockaddr *

連結成功會把用戶端的位址資訊存入改結構體

__restrict __addr_len 第二個傳入的參數修改以後的實際大小

NOTE

:連結成功則傳回一個檔案描述符(以後的通信都使用它),

-1

則建立失敗

connect

函數

函數原型如下:

/* Open a connection on socket FD to peer at ADDR (which LEN bytes long).
   For connectionless socket types, just set the default address to send to
   and the only address from which to accept transmissions.
   Return 0 on success, -1 for errors.

   This function is a cancellation point and therefore not marked with
   __THROW.  */
extern int connect (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len);
           

參數含義:

__fd 用戶端調用

scoket()

函數建立成功的檔案描述符(file descriptor)

__addr 的類型其實是

struct sockaddr *

需要建立連結的服務端的位址和端口資訊(必須是網絡位元組序)

__len 第二個參數結構體的大小

NOTE

:傳回

代表成功

-1

代表失敗

使用例子:

struct sockaddr_in clientAddr;
    struct sockaddr_in serverAddr;
    int socket_fd=-1;
    
    bzero(&clientAddr, sizeof(clientAddr));
    clientAddr.sin_family = AF_INET;
    clientAddr.sin_addr.s_addr = htons(INADDR_ANY);
    clientAddr.sin_port = htons(0);
    //建立client
    socket_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (socket_fd < 0) {
        fprintf(stderr, "initial tcp_client create socket failed\n");
        return -1;
    }
    // 3.将socket建立為非阻塞,此時socket被設定為非阻塞模式
    int flags = fcntl(socket_fd, F_GETFL, 0);       //擷取建立的sockfd的目前狀态(非阻塞)
    fcntl(socket_fd, F_SETFL, flags | O_NONBLOCK);  //将目前sockfd設定為非阻塞
    if (bind(socket_fd, (struct sockaddr *)&clientAddr, sizeof(clientAddr)) == -1) {
        fprintf(stderr, "initial tcp_client bind socket failed\n");
        return -1;
    }
    bzero(&serverAddr, sizeof(serverAddr));
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_addr.s_addr = inet_addr(tcp_server_ip);
    serverAddr.sin_port = htons(tcp_server_port);
    if(connect(socket_fd, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) == -1) {
    	fprintf(stderr, "connet to server failed\n");
    	return -1;
    }
           

詳細使用方法參照

繼續閱讀