歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Linux下socket編程學習

相關結構

//下邊這兩個結構定義在<sys/types.h>裡
//一般的地址結構,只能用於覆蓋(把其他地址轉換為此類型),且只能引用該地址的sa_family字段
 struct sockaddr
    {
    unsigned char sa_len;   //total length,整個結構體的長度,舊版本沒有
    unsigned short  sa_family;   //地址族
    char    sa_data[14];   //地址的值
  
  //TCP/IP使用的地址結構
struct sockaddr_in
    {
       unsigned char    sin_len;    //total length
       short int                     sin_family;   //地址族,一般為AF_INET(ipv4),ipv6為(AF_INET6)
       unsigned short int      sin_port;      //端口號
       struct in_addr             sin_addr;      //ip地址
       char             sin_zero[8];  //沒有使用(設置為0)
    }

相關函數-主調用

如果函數調用失敗,都返回-1,調用失敗會在全局變量error裡有相應的值
不涉及到讀取、發送的時候,調用正常都返回0

socket()

創建套接字

int socket(int family, int type, int protocol)

family: 協議或地址族,TCP/IP為PF_INET,(ipv6為PF_INET6),也可以使用AF_INET
type: 套接字類型

  • 流式套接字:SCOK_STREAM, TCP
  • 數據報套接字:SOCK_DGRAM,UDP
  • 原始套接字:SOCK_RAW,沒有經過處理的IP數據包,可以根據自己程序的要求進行封裝

protocol:用來指定socket所使用的傳輸協議編號,通常設為0即可。

調用成功返回描述符

connect()

為套接字指明遠程端點的地址。為TCP時,connect使用三次握手建立連接;為UDP時,connect僅指明遠程端點,但是不向他發送任何數據

int connect(int sock, struct sockaddr \*serv_addr, int addrlen)

sock: 目的服務器的socket描述符
serv_addr:包含目的機器ip地址和端口號的指針
addrlen:sizeof(struct sockaddr)
調用成功返回0

send()/write() -TCP

linux下可以使用write(),將報文傳遞給目標主機

(int sock, char\* msg, int msglen, int flags);

flags:控制bit,指明是否接受帶外數據和是否預覽報文,一般為0

write(int sock, char* buf,  int buflen)

buf:含有數據緩存的地址
buflen:buf中的字節數
這兩個函數調用成功時都返回傳送的字節數

recv()/read() -TCP

從套接字中接收數據

nt recv(int sock, char\* buf, int len, int flags)

buf:存放數據的緩存地址
len:緩存的長度
flags:控制bit,指明是否接受帶外數據和是否預覽報文一般為0

read(int sock, char* buf,  int buflen)

調用成功都返回讀取的字節數

sendto() -UDP

從一個結構中獲取目的地址,然後發送報文

int sendto(int sock, char \*msg, int msglen, int flags, const struct sockaddr\* to, int\* tolen);

tolen:地址結構的字節長度
成功時,返回已發送的字節數

recvfrom() -UDP

從套接字獲取下一個傳入報文,並記錄發送者的地址

 int recvfrom(int sock, char\* buf, int buflen, int flags, struct sockaddr\* from, int\* fromlen)
 ```
fromlen:緩存的長度,返回時為發送者地址的大小。
成功調用時,返回報文中的字節數

### bind()
主要由服務器使用,指明本地ip地址和協議端口號

int bind(int sock, struct sockaddr *localaddr, int addrlen)

成功時返回0

### listen() -TCP
服務器調用,使套接字處於被動狀態(准備接受傳入請求)

int listen ( sock,queuelen)

queuelen:傳入鏈接請求的隊列大小(通常最大不超過5)

### accept() -TCP
bind->listen->accept,從隊列中取走下一個鏈接請求(或者一直在那裡等待下一個連接請求到來),為請求創建新套接字,並返回新套接字描述符。

int accept(int sock, struct sockaddr * addr, int* addrlen)

addrlen:初始指明為addr的大小,調用返回時為存儲在addr中的字節數

### close()
終止通信,刪除套接字,任何正在套接字上等待被讀取的數據都將被拋棄。  
linux使用了引用計數機制,可以多個進程共享一個套接字。close每被調用一次,引用計數減1,引用計數為0時才釋放。

int close(int sock)

成功時返回0

### shutdown()
部分關閉連接

int shutdown(int sock,int direction )

direction:0,終止進一步輸入;1,終止進一步輸出;2,終止輸入和輸出

## 輔助函數
### 整數轉換
TCP/IP協議首部使用的二進制采用網絡字節順序(表示整數時,最高字節在前)  
為了機器和網絡字節順序兼容,應當始終調用轉換函數  

htons(host to network short)
ntohs
htonl
ntohl


### 地址轉換inet_addr
接受字符串(點分十進制),返回等價二進制表示的地址

serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
```

查找域名對應ip地址gethostbyname

接收ASCII字符串域名,返回hostent結構,定義在<netdb.h>

struct hostent
{
    char*    h_name,    //正式主機名
    char**   h_aliases, //其他別名列表
    int      h_addrtype,    //地址類型
    int      h_length,  //地址長度
    char**   h_addr_list    //一般主機可以有多個ip地址,h_addr_list用來
保存多個ip地址
}
#define h_addr h_addr_list[0]   //為了與早期的版本兼容

由服務名字得到熟知端口getservbyname

成功則返回一個servent結構指針,發生差錯就返回空指針,結構定義在<netdb.h>

servent* getservbyname(char\* name, char\* proto)

struct servent
{
char* s_name; //正式服務名
char** s_aliases; //其他別名列表
int s_port; //該服務使用的端口
char *s_proto; //服務器所用的協議
};
```

根據協議名找到該協議的正式整數值getprotobyname(char* name)

成功就返回protoent結構指針,結構定義在<netdb.h>

struct protoent
{
    char\*      p_name; //協議正式名
    char\*\*    p_aliases;  //協議的別名列表
    int         p_proto;        //正式協議名
}

獲取主機名字gethostname

以字符串形式返回主機名

int gethostname(char\* name, namelen)

name:放置名字的字符數組的地址

獲取遠程端點地址getpeername

需要已經建立鏈接

int getpeername(int sock, sockaddr\* remaddr, int\* addrlen)

remaddr:含有對端地址的sockaddr指針
addrlen:調用前為第二個參數的長度,調用後為遠程端點地址的實際長度

設置/查看套接字參數

getsockopt()
setsockopt()

相關頭文件

<sys/types.h>           //primitive system data types(包含很多類型重定義,如pid_t、int8_t等) 
<sys/socket.h>         //與套接字相關的函數聲明和結構體定義,如socket()、bind()、connect()及struct sockaddr的定義等
//上邊兩個sock調用必須包含
<netinet/in.h>          //某些結構體聲明、宏定義,如struct sockaddr_in、struct inaddr 、PROTO_ICMP、INADDR_ANY等
<sys/types.h>           //primitive system data types(包含很多類型重定義,如pid_t、int8_t等) 
<sys/socket.h>         //與套接字相關的函數聲明和結構體定義,如socket()、bind()、connect()及struct sockaddr的定義等
<sys/ioctl.h>             //I/O控制操作相關的函數聲明,如ioctl()
<stdlib.h>                   //某些結構體定義和宏定義,如EXIT_FAILURE、EXIT_SUCCESS等
<netdb.h>                  //某些結構體定義、宏定義和函數聲明,如struct hostent、struct servent、gethostbyname()、gethostbyaddr()、herror()等
<arpa/inet.h>           //某些函數聲明,如inet_ntop()、inet_ntoa()等
<netinet/in.h>          //某些結構體聲明、宏定義,如struct sockaddr_in、PROTO_ICMP、INADDR_ANY等

Copyright © Linux教程網 All Rights Reserved