1.socket程式設計:socket程式設計,網路位元組序,函式介紹,IP地址轉換函式,sockaddr資料結構,網路套接字函式,socket相關函式,TCP server和client
1Socket程式設計
socket這個詞可以表示很多概念:
在TCP/IP協議中,“IP地址+TCP或UDP埠號”唯一標識網路通訊中的一個程序,“IP
地址+埠號”就稱為socket。
在TCP協議中,建立連線的兩個程序各自有一個socket來標識,那麼這兩個socket組成的socket pair就唯一標識一個連線。socket本身有“插座”的意思,因此用來描述網路連
接的一對一關係。
TCP/IP協議最早在BSD UNIX上實現,為TCP/IP協議設計的應用層程式設計介面稱為socket
API。
本章的主要內容是socketAPI,主要介紹
圖11.1:socketAPI
2 網路位元組序
我們已經知道,記憶體中的多位元組資料相對於記憶體地址有大端和小端之分,磁碟檔案中的
多位元組資料相對於檔案中的偏移地址也有大端小端之分。網路資料流同樣有大端小端之分,
那麼如何定義網路資料流的地址呢?傳送主機通常將傳送緩衝區中的資料按記憶體地址從低到高的順序發出,接收主機把從網路上接到的位元組依次儲存在接收緩衝區中,也是按記憶體地址從低到高的順序儲存,因此,網路資料流的地址應這樣規定:先發出的資料是低地址,後發出的資料是高地址。
TCP/IP協議規定,網路資料流應採用大端位元組序,即低地址高位元組。例如上一節的UDP
段格式,地址0-1是16位的源埠號,如果這個埠號是1000(0x3e8),則地址0是0x03,
地址1是0xe8,也就是先發0x03,再發0xe8,這16位在傳送主機的緩衝區中也應該是低地址存0x03,高地址存0xe8。但是,如果傳送主機是小端位元組序的,這16位被解釋成0xe803,而不是1000。因此,傳送主機把1000填到傳送緩衝區之前需要做位元組序的轉換。同樣地,接收主機如果是小端位元組序的,接到16位的源埠號也要做位元組序的轉換。如果主機是大端位元組序的,傳送和接收都不需要做轉換。同理,32位的IP地址也要考慮網路位元組序和主機位元組序的問題。
為使網路程式具有可移植性,使同樣的C程式碼在大端和小端計算機上編譯後都能正常執行,可以呼叫以下庫函式做網路位元組序和主機位元組序的轉換。
3 函式介紹
A 依賴的標頭檔案
#include <arpa/inet.h>
B 函式宣告
#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);
h表示host,n表示network,l表示32位長整數,s表示16位短整數。
如果主機是小端位元組序,這些函式將引數做相應的大小端轉換然後返回,如果主機是大端位元組序,這些函式不做轉換,將引數原封不動地返回。
uint32_t htonl(uint32_t hostlong);
名稱: |
htonl |
功能: |
The htonl() function converts the unsigned integer hostlongfromhost byte order to network byte order |
標頭檔案: |
#include <arpa/inet.h> |
函式原形: |
uint32_t htonl(uint32_t hostlong); |
引數: |
|
返回值: |
uint16_t htons(uint16_t hostshort);
名稱: |
htons |
功能: |
The htons() function converts the unsigned short integer hostshort from host byte order to network byte order. |
標頭檔案: |
#include <arpa/inet.h> |
函式原形: |
uint16_t htons(uint16_t hostshort); |
引數: |
|
返回值: |
uint32_t ntohl(uint32_t netlong);
名稱: |
ntohl |
功能: |
The ntohl() function converts the unsigned integer netlong from network byte order to host byte order. |
標頭檔案: |
#include <arpa/inet.h> |
函式原形: |
uint32_t ntohl(uint32_t netlong); |
引數: |
|
返回值: |
uint16_t ntohs(uint16_t netshort);
名稱: |
ntohs |
功能: |
The ntohs() function converts the unsigned short integer netshort from network byte order to host byte order. |
標頭檔案: |
#include <arpa/inet.h> |
函式原形: |
uint16_t ntohs(uint16_t netshort); |
引數: |
|
返回值: |
4 IP地址轉換函式
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int inet_aton(const char *cp, structin_addr *inp);
in_addr_t inet_addr(const char *cp);
char *inet_ntoa(struct in_addr in);
只能處理IPv4的ip地址
不可重入函式
注意引數是struct in_addr
現在
#include <arpa/inet.h>
int inet_pton(int af, const char *src, void*dst);
const char *inet_ntop(int af, const void*src, char *dst, socklen_t size);
支援IPv4和IPv6
可重入函式
其中inet_pton和inet_ntop不僅可以轉換IPv4的in_addr,還可以轉換IPv6的in6_addr,因此函式介面是void*addrptr
5 sockaddr資料結構
strcutsockaddr 很多網路程式設計函式誕生早於IPv4協議,那時候都使用的是sockaddr結
構體,為了向前相容,現在sockaddr退化成了(void *)的作用,傳遞一個地址給函式,至
於這個函式是sockaddr_in還是sockaddr_in6,由地址族確定,然後函式內部再強制型別轉
化為所需的地址型別
圖 11.2:sockaddr資料結構
struct sockaddr {
sa_family_t sa_family; /* address family, AF_xxx */
char sa_data[14]; /* 14 bytes of protocol address */
};
struct sockaddr_in {
__kernel_sa_family_t sin_family; /* Address family */
__be16 sin_port; /* Port number */
struct in_addr sin_addr; /* Internet address */
/* Pad to size of `struct sockaddr'. */
unsigned char __pad[__SOCK_SIZE__ - sizeof(short int) -
sizeof(unsigned short int) - sizeof(struct in_addr)];
};
/* Internet address. */
struct in_addr {
__be32 s_addr;
};
struct sockaddr_in6 {
unsigned short int sin6_family; /* AF_INET6*/
__be16 sin6_port; /* Transport layer port # */
__be32 sin6_flowinfo; /* IPv6 flow information */
struct in6_addr sin6_addr; /* IPv6 address */
__u32 sin6_scope_id; /* scope id (new in RFC2553) */
};
struct in6_addr {
union {
__u8 u6_addr8[16];
__be16 u6_addr16[8];
__be32 u6_addr32[4];
} in6_u;
#define s6_addr in6_u.u6_addr8
#define s6_addr16 in6_u.u6_addr16
#define s6_addr32 in6_u.u6_addr32
};
#define UNIX_PATH_MAX 108
struct sockaddr_un {
__kernel_sa_family_t sun_family; /* AF_UNIX */
char sun_path[UNIX_PATH_MAX]; /* pathname */
};
Pv4和IPv6的地址格式定義在netinet/in.h中,IPv4地址用sockaddr_in結構體表示,包
括16位埠號和32位IP地址,IPv6地址用sockaddr_in6結構體表示,包括16位埠號、128位IP地址和一些控制欄位。UNIX Domain Socket的地址格式定義在sys/un.h中,用sockaddr_un結構體表示。各種socket地址結構體的開頭都是相同的,前16位表示整個結構體的長度(並不是所有UNIX的實現都有長度欄位,如Linux就沒有),後16位表示地址型別。IPv4、IPv6和Unix Domain Socket的地址型別分別定義為常數AF_INET、AF_INET6、AF_UNIX。這樣,只要取得某種sockaddr結構體的首地址,不需要知道具體是哪種型別的sockaddr結構體,就可以根據地址型別欄位確定結構體中的內容。因此,socket API可以接受各種型別的sockaddr結構體指標做引數,例如bind、accept、connect等函式,這些函式的引數應該設計成void *型別以便接受各種型別的指標,但是sock API的實現早於ANSI C標準化,那時還沒有void *型別,因此這些函式的引數都用struct sockaddr *型別表示,在傳遞引數之前要強制型別轉換一下,例如:
struct sockaddr_in servaddr;
/* initialize servaddr */
bind(listen_fd,(struct sockaddr*)&servaddr,sizeof(servaddr));
6 網路套接字函式
A socket
#include <sys/types.h>
#include <sys/socket.h>
int socket(int domain,int types,intprotocol);
domain:
AF_INET 這是大多數用來產生socket的協議,使用TCP或UDP來傳輸,用IPv4的地址
AF_INET6 與上面類似,不過是來用IPv6的地址
AF_UNIX 本地協議,使用在Unix和Linux系統上,一般都是當客戶端和伺服器在同一臺及其上的時候使用
type:
SOCK_STREAM 這個協議是按照順序的、可靠的、資料完整的基於位元組流的連線。這是一個使用最多的socket型別,這個socket是使用TCP來進行傳輸。
SOCK_DGRAM 這個協議是無連線的、固定長度的傳輸呼叫。該協議是不可靠的,使用UDP來進行它的連線。
SOCK_SEQPACKET 這個協議是雙線路的、可靠的連線,傳送固定長度的資料包進行傳輸。必須把這個包完整的接受才能進行讀取。
SOCK_RAW 這個socket型別提供單一的網路訪問,這個socket型別使用ICMP公共協議。(ping、traceroute使用該協議)
SOCK_RDM 這個型別是很少使用的,在大部分的作業系統上沒有實現,它是提供給資料鏈路層使用,不保證資料包的順序
protocol:
0 預設協議
返回值:
成功返回一個新的檔案描述符,失敗返回-1,設定errno
socket()開啟一個網路通訊埠,如果成功的話,就像open()一樣返回一個檔案描述符,應用程式可以像讀寫檔案一樣用read/write在網路上收發資料,如果socket()調用出錯則返回-1。對於IPv4,domain引數指定為AF_INET。對於TCP協議,type引數指定為SOCK_STREAM,表示面向流的傳輸協議。如果是UDP協議,則type引數指定為SOCK_DGRAM,表示面向資料報的傳輸協議。protocol引數的介紹從略,指定為0即可。
7 bind
A 依賴的標頭檔案
#include <sys/types.h> /* See NOTES*/
#include <sys/socket.h>
B 函式宣告
int bind(int sockfd, const struct sockaddr*addr, socklen_t addrlen);
sockfd:
socket檔案描述符
addr:
構造出IP地址加埠號
addrlen:
sizeof(addr)長度
返回值:
成功返回0,失敗返回-1,設定errno
伺服器程式所監聽的網路地址和埠號通常是固定不變的,客戶端程式得知伺服器程式
的地址和埠號後就可以向伺服器發起連線,因此伺服器需要呼叫bind繫結一個固定的網路地址和埠號。
bind()的作用是將引數sockfd和addr繫結在一起,使sockfd這個用於網路通訊的檔案
描述符監聽addr所描述的地址和埠號。前面講過,struct sockaddr *是一個通用指標類
型,addr引數實際上可以接受多種協議的sockaddr結構體,而它們的長度各不相同,所以需要第三個引數addrlen指定結構體的長度。如:
struct sockaddr_in servaddr;
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr =htonl(INADDR_ANY);
servaddr.sin_port = htons(8000);
首先將整個結構體清零,然後設定地址型別為AF_INET,網路地址為INADDR_ANY,這個巨集表示本地的任意IP地址,因為伺服器可能有多個網絡卡,每個網絡卡也可能繫結多個IP地址,這樣設定可以在所有的IP地址上監聽,直到與某個客戶端建立了連線時才確定下來到底用哪個IP地址,埠號為8000。
8 listen
#include <sys/types.h> /* See NOTES*/
#include <sys/socket.h>
int listen(int sockfd, int backlog);
sockfd:
socket檔案描述符
1Socket程式設計
socket這個詞可以表示很多概念:
在TCP/IP協議中,“IP地址+TCP或UDP埠號”唯一標識網路通訊中的一個程序,“IP
地址+埠號”就
雙十一
今天是雙十一,記得還在念書的時候,每次都會參加京東圖書滿200-100的活動,然後腦子一熱屯一堆書。印象中人文類的書基本都會看,而電子資訊類的可能就只看了一半,甚至買過哪些都忘了。究其原因,主要是人文類的通常都是自己想看的,而技術類的就跟風看哪個銷量大買
1.錯誤描述
在VMware中開啟虛擬機器時報錯:
“無法連線MKS:套接字連線嘗試次數太多,正在放棄”
物理機作業系統:
Windows 7
虛擬機器作業系統:
Kali Linux
開發環境:
我在windows上使用的是VMware Workstation 14 Pro+Ubuntu16.04的組合進行開發。
原因:
自從將vm從12pro升級成了14pro之後就出現了這種問題,應該是14pro版本本身還有些問題吧。
解決方法:
運行 accep index lines sleep div rri object art
import java.io.PrintWriter
import java.net.ServerSocket
import scala.io.Source
object D
一、傳輸層socket(四層socket,普通socket)
可參考本人以下部落格:
(1)建立
socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);//TCP
//或者
socket(AF_INET,SOCK_DGRAM,I
socket
思路:客戶端連線伺服器,當客戶端要退出時,首先要關閉兩者之間的通訊,再將其各自的處理類所在的執行緒關閉掉。
在做多執行緒的猜拳小遊戲中,其
1,什麼是大小端?大小端是指資料在記憶體的的存放順序,現代計算機一次能夠載入32bit或者64bit的資料或者指令,因而資料的存放順序影響它被裝載到整數的值。以小端來講:低地址存資料的低位,高地址存資料的高;而大端敲好反過來:高地址存低位,地址存高位。2.測試大小端測試大小端
文章目錄
1,socket
1.1,socket的型別(SOCK_STREAM、SOCK_DGRAM、SOCK_RAW)
1.2,socket的位置
2,IP地址
2.1,特殊IP地址:
3,埠號
Socket(套接字)
socket可以看成是使用者程序與核心網路協議棧的程式設計介面(API函式)。 socket不僅可以用於本機的程序間通訊,還可以用於網路上不同主機的程序間通訊。
IPv4套接字地址結構
IPv4套接字地址結構通常也稱為“網際套接字地址結構”,它以
基本概念
套接字——應用層和傳輸層之間,提供應用傳輸介面
Web/RPC/中介軟體——應用層之上的網路開發
應用程式設計介面API(application programming interface)
套接字介面(socket interface)簡稱套接字,
1.套接字概念回顧
(1)套接字是一個識別符號;
(2)套接字是一個結構;
(3)套接字是一個包含標識、資料和操作的複合體,是服務訪問點。
我們已經知道,一個套接字描述符s實際上是一個整形資料,在winsock.h標頭檔案中,SOCKET是這樣被定義的:
與UDP不同,TCP是一個面向連線的協議。這意味著,在客戶端和伺服器能夠開始互相傳送資料之前,它們要先握手和建立一個TCP連線。連線建立之後,當有一方需要給另一方傳送資料,它只需經套接字把資料丟個TCP連線,無需再為資料附上目的地地址。1. 下面討論一下TCP客
網路程式設計:
java語言中,提供了一套統一的程式設計介面。很多細節都已經底層化。
所在,可以進行無痛的網路通訊程式設計。
提供的是Socket套接字技術。
--常用的通訊協議:
(1)TCP/IP:在通訊之前,需
在客戶機/伺服器工作模式中,在Server端,要準備接受多個Client端計算機的通訊。為此,除用IP地址標識Internet上的計算機之外,另還引入埠號,用埠號標識正在Server端後臺服務的執行緒。埠號與IP地址的組合稱為網路套接字(socket)。
Java語言在
<span style="font-family: Arial, Helvetica, sans-serif;">server.c</span>
=================================================== void send_fd(int sock_fd, int send_fd)
{
int ret;
struct msghdr msg;
struct cmsghdr *p_cmsg;
struct iovec vec;
char cmsgbuf[CMSG_SPACE(
CSDN的部落格中有這樣一篇部落格點選開啟連結,是關於TCP的socket程式設計的,我想基於我的理解解釋一下,畢竟原文只給出了純粹的程式碼,
我們知道上圖是它們之間的工作模式,基本程式設計的規則也是按照上面來的
下面是伺服器端的程式碼,但插入的程式碼本應該是C的,但是
一、簡單的tcp套接字通訊
套接字通訊的一般流程
服務端
server = socket() #建立伺服器套接字
server.bind() #把地址繫結到套接字,網路地址加埠
server.listen() #監聽連結
inf_loop:
1.埠
在進行通訊的時候,要首先通過IP地址獲取主機
再通過Port用來區分和主機上的哪個應用程式通訊
2.IPv4套介面地址結構:網際套接字地質結構 sockaddr_in:man 7 ip
1.標頭檔案:netinet/in.h
2.sockaddr_in結構
struct 相關推薦
1.socket程式設計:socket程式設計,網路位元組序,函式介紹,IP地址轉換函式,sockaddr資料結構,網路套接字函式,socket相關函式,TCP server和client
走進Linux核心網路 套接字的祕密—socket與sock
解決VMware虛擬機器報錯“無法連線MKS:套接字連線嘗試次數太多,正在放棄”
虛擬機器出現錯誤:“無法連線MKS:套接字連線嘗試次數太多,正在放棄“,無法進入系統的解決方法
IDEA Spark Streaming 操作(套接字流)-----make socket數據源
raw_socket(原始套接字)以及普通socket使用終極總結
針對套接字關閉異常:Socket closed解決方案
一些基本問題:大小端,網路位元組序,socket程式設計函式的注意點,gdb和coredump除錯
嵌入式Linux網路程式設計,網路基礎,套接字socket(SOCK_STREAM、SOCK_DGRAM、SOCK_RAW),IP地址,埠號,位元組序,位元組序轉換函式,IP地址的轉換
Linux網路程式設計:socket程式設計簡介、網路位元組序及相關函式
socket程式設計 套接字程式設計 (純理論,以後補一下實現程式碼)
socket網路程式設計複習筆記(三):套接字描述符背後的祕密
TCP套接字程式設計 整理《計算機網路——自頂向下方法(James F. Kurose, Keith W. Rose)》
網路程式設計、常用的通訊協議、Socket套接字程式設計(Socket和ServerSocket)、埠號
網路程式設計二(套接字Socket、客戶端和服務端通訊問題)
linux下socket通訊,server和client簡單例子
linux網路程式設計之socket(十六):通過UNIX域套接字傳遞描述符和 sendmsg/recvmsg 函式
關於linux下的TCP 的socket server和client,我的理解
Python之路(第三十一篇) 網路程式設計:簡單的tcp套接字通訊、粘包現象
1.socket基礎知識:埠;sockaddr_in;位元組序轉換函式(本地/網路位元組序);地址轉換函式