Socket網(wǎng)絡(luò)編程

套接字概念

Socket本身有“插座”的意思吱涉,在Linux環(huán)境下逛薇,用于表示進(jìn)程間網(wǎng)絡(luò)通信的特殊文件類型捺疼。本質(zhì)為內(nèi)核借助緩沖區(qū)形成的偽文件。

既然是文件永罚,那么理所當(dāng)然的啤呼,我們可以使用文件描述符引用套接字。與管道類似的呢袱,Linux系統(tǒng)將其封裝成文件的目的是為了統(tǒng)一接口官扣,使得讀寫(xiě)套接字和讀寫(xiě)文件的操作一致。區(qū)別是管道主要應(yīng)用于本地進(jìn)程間通信羞福,而套接字多應(yīng)用于網(wǎng)絡(luò)進(jìn)程間數(shù)據(jù)的傳遞惕蹄。

套接字的內(nèi)核實(shí)現(xiàn)較為復(fù)雜,不宜在學(xué)習(xí)初期深入學(xué)習(xí)治专。

在TCP/IP協(xié)議中卖陵,“IP地址+TCP或UDP端口號(hào)”唯一標(biāo)識(shí)網(wǎng)絡(luò)通訊中的一個(gè)進(jìn)程≌欧澹“IP地址+端口號(hào)”就對(duì)應(yīng)一個(gè)socket泪蔫。欲建立連接的兩個(gè)進(jìn)程各自有一個(gè)socket來(lái)標(biāo)識(shí),那么這兩個(gè)socket組成的socket pair就唯一標(biāo)識(shí)一個(gè)連接挟炬。因此可以用Socket來(lái)描述網(wǎng)絡(luò)連接的一對(duì)一關(guān)系鸥滨。

套接字通信原理如下圖所示:

套接字通訊原理示意

在網(wǎng)絡(luò)通信中,套接字一定是成對(duì)出現(xiàn)的谤祖。一端的發(fā)送緩沖區(qū)對(duì)應(yīng)對(duì)端的接收緩沖區(qū)婿滓。我們使用同一個(gè)文件描述符索發(fā)送緩沖區(qū)和接收緩沖區(qū)。

TCP/IP協(xié)議最早在BSD UNIX上實(shí)現(xiàn)粥喜,為TCP/IP協(xié)議設(shè)計(jì)的應(yīng)用層編程接口稱為socket API⊥怪鳎現(xiàn)在的主要內(nèi)容是socket API,主要介紹TCP協(xié)議的函數(shù)接口额湘,最后介紹UDP協(xié)議和UNIX Domain Socket的函數(shù)接口卿吐。

網(wǎng)絡(luò)編程接口

1、什么是計(jì)算機(jī)網(wǎng)絡(luò)锋华?

? 多個(gè)計(jì)算機(jī)進(jìn)行通信--->計(jì)算機(jī)網(wǎng)絡(luò)嗡官。

2、計(jì)算機(jī)通信的復(fù)雜度

? (1)毯焕、傳輸信息的復(fù)雜度(種類衍腥、內(nèi)容);

? (2)纳猫、信息的數(shù)量

? (3)婆咸、傳輸距離(干擾...)

? (4)、信息的安全問(wèn)題

? (5)芜辕、計(jì)算機(jī)體系的完整性和封閉性尚骄。

? 既要保證計(jì)算機(jī)的封閉性,又要達(dá)成計(jì)算機(jī)的通信侵续。

3倔丈、ip地址

? (1)、IP地址是有限的询兴,需要一種方式將IP地址復(fù)用乃沙。

? (2)、IP地址的復(fù)用導(dǎo)致了數(shù)據(jù)傳遞的復(fù)雜性(ATM诗舰,存儲(chǔ)轉(zhuǎn)發(fā)機(jī)制警儒;路由機(jī)制)。

? (3)眶根、IP地址過(guò)于抽象不方便使用蜀铲,于是給出了IP地址的人文化轉(zhuǎn)義:域名。

? (4)属百、域名只能代表一個(gè)IP網(wǎng)絡(luò)地址记劝,于是就只能代表一個(gè)網(wǎng)絡(luò)上的節(jié)點(diǎn)實(shí)體。

? (5)族扰、實(shí)際上訪問(wèn)節(jié)點(diǎn)的時(shí)候厌丑,本質(zhì)上使用的是IP地址定欧,所以就需要將域名轉(zhuǎn)化為IP地址(DNS...)

4、IP地址的分類

? (1)怒竿、IPv4地址是4字節(jié)的砍鸠,中間以 . 劃分;IPv6地址是16字節(jié)的耕驰;

規(guī)定:在IP地址劃分上爷辱,一般不取全0/全1;

? IP一般分為5類;

? A朦肘、B饭弓、C、D媒抠、E弟断,一般常用的IP地址為A類,B類趴生,C類夫嗓;

A類IP:第一個(gè)字節(jié)是以0開(kāi)頭0000 0000--->0111 11110~127

B類IP:第一個(gè)字節(jié)是以10開(kāi)頭1000 0000--->1011 1111128~191

C類IP:第一個(gè)字節(jié)是以110開(kāi)頭1100 0000--->1101 1111192~223

??(2)、子網(wǎng)掩碼:就是將網(wǎng)絡(luò)號(hào)設(shè)置為1冲秽,主機(jī)號(hào)設(shè)置為0(對(duì)每一個(gè)字節(jié)的位進(jìn)行設(shè)置)舍咖;

? 例:C類IP地址,3個(gè)字節(jié)網(wǎng)絡(luò)號(hào)和一個(gè)字節(jié)的主機(jī)號(hào)锉桑;

? 1111 1111 1111 1111 1111 1111 0000 0000

???? 255?????? .???? 255???? .????? 255???? .???? 0

(3)排霉、子網(wǎng)劃分:此時(shí)就存在C類地址的子網(wǎng)掩碼不一定總是255.255.255.0;

??這還的看C類IP下面有沒(méi)有子網(wǎng)劃分,

? 有子網(wǎng)劃分的話民轴,最后一個(gè)字節(jié)攻柠,也就是主機(jī)號(hào)可能為2段(01/10)、4段(00/01/10/11)

例:192.168.3.11xx xxxx? 1111 1111 1111 1111 1111 11111100 0000

? 此時(shí)對(duì)應(yīng)的子網(wǎng)掩碼為:255.255.255.192

? (4)后裸、IOS和TCP/IP

模型分析

? (5)瑰钮、端口號(hào)

? port:唯一標(biāo)識(shí)應(yīng)用程序的編號(hào);

我們之間通過(guò)QQ微驶、微信浪谴、郵箱進(jìn)行收發(fā)數(shù)據(jù)時(shí),沒(méi)有導(dǎo)致數(shù)據(jù)的錯(cuò)亂接收因苹,是怎么做到的呢苟耻?又是怎么一一對(duì)應(yīng)找到的呢?

? :通過(guò)端口號(hào)扶檐,識(shí)別了電腦上的某一應(yīng)用程序凶杖,也就是找對(duì)應(yīng)的編號(hào)。

? 我們?cè)谶M(jìn)行數(shù)據(jù)的發(fā)送時(shí):首先通過(guò)IP尋找物理計(jì)算機(jī)款筑,在根據(jù)port智蝠,尋找對(duì)應(yīng)的應(yīng)用程序腾么。

??(6)、TCP和UDP

UDP屬于TCP/IP體系中的一部分杈湾。

??TCP協(xié)議和UDP協(xié)議都屬于傳輸層協(xié)議哮翘。

? TCP協(xié)議:

? i>、面向連接的傳輸協(xié)議毛秘、可靠的、同步的阻课;

? ii>叫挟、面向連接的網(wǎng)絡(luò)傳輸特點(diǎn):a、需要有一方主動(dòng)的建立連接限煞,另一方接收連接請(qǐng)求抹恳;b、只有建立了連接之后才能夠進(jìn)行數(shù)據(jù)的傳輸署驻;c奋献、當(dāng)數(shù)據(jù)傳輸完畢之后,就需要釋放連接旺上,由連接的兩端來(lái)共同決定連接是否保持瓶蚂。

? UDP協(xié)議:

? a、面向無(wú)連接的:即就是在進(jìn)行數(shù)據(jù)傳輸?shù)臅r(shí)候宣吱,不需要預(yù)先創(chuàng)建一個(gè)連接窃这;

? b、不可靠的:無(wú)法知道發(fā)送的數(shù)據(jù)是否能夠到達(dá)目的征候,也無(wú)法知道什么時(shí)候能夠到達(dá)目的杭攻。

? c、異步的:

? (7)疤坝、TCP的三次握手兆解、四次揮手

TCP------->至少3次握手(最后一次防止誤按,2次的話跑揉,有可能死鎖)锅睛;??? : 打電話模型

? 模型分析

? TCP-------->4次揮手。? 模型:男女朋友分手模型

? 通過(guò)IP历谍,只能保證物理上的連通衣撬,至于收發(fā)數(shù)據(jù)的形式是什么,都不歸它管扮饶。

? 127.0.0.1:本機(jī)回送地址具练,可作為測(cè)試本機(jī)使用,不安裝網(wǎng)卡也是可以ping通的甜无。

5扛点、TCP的編程實(shí)現(xiàn)

基礎(chǔ)的socket編程對(duì)TCP的就是下面的步驟:

(1)哥遮、模型分析

(2)、代碼實(shí)現(xiàn)

utili.h

#include

#include

#include

#include

#include

#include

#define SERVER_PORT 9090

#define SERVER_IP ?"127.0.0.1"

#define LISTEN_QUEUE ? ?5

#define BUF_SIZE ? ?255

服務(wù)器端代碼:

#include"utili.h"http://TCP

int main(void)

{

int sockSer = socket(AF_INET, SOCK_STREAM, 0);

if(sockSer == -1){

perror("socket");

return -1;

}

struct sockaddr_in addrSer, addrCli;

addrSer.sin_family = AF_INET;

addrSer.sin_port = htons(SERVER_PORT);

addrSer.sin_addr.s_addr = inet_addr(SERVER_IP);

int yes = 1;

setsockopt(sockSer, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)); //地址陵究、端口的重用

socklen_t len = sizeof(struct sockaddr);

int res = bind(sockSer, (struct sockaddr *)&addrSer, len);

if(res == -1)

{

perror("bind");

close(sockSer);

return -1;

}

res = listen(sockSer, LISTEN_QUEUE);

if(res == -1)

{

perror("listen");

close(sockSer);

return -1;

}

int sockConn;

char sendbuf[BUF_SIZE];

char recvbuf[BUF_SIZE];

while(1)

{

sockConn = accept(sockSer, (struct sockaddr *)&addrCli, &len);

if(sockConn == -1){

continue;

}

else

{

printf("Server Accept Client Connect OK\n");

}

printf("Ser :>");

scanf("%s", sendbuf);

if(strncmp(sendbuf, "quit", 4) == 0)

break;

send(sockConn, sendbuf, strlen(sendbuf)+1, 0);

recv(sockConn, recvbuf, BUF_SIZE, 0);

printf("Cli :>%s\n", recvbuf);

}

close(sockSer);

return 0;}

客戶端代碼:

#include"utili.h"http://TCP

int main(void)

{

int sockCli = socket(AF_INET, SOCK_STREAM, 0);

struct sockaddr_in addrSer;

addrSer.sin_family = AF_INET;

addrSer.sin_port = htons(SERVER_PORT);

addrSer.sin_addr.s_addr = inet_addr(SERVER_IP);

struct sockaddr_in addrCli;

addrCli.sin_family = AF_INET;

addrCli.sin_port = htons(7070);

addrCli.sin_addr.s_addr = inet_addr("192.168.1.155");

int yes = 1;

setsockopt(sockCli, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)); //地址眠饮、端口的重用

socklen_t len = sizeof(struct sockaddr);

int res = bind(sockCli, (struct sockaddr *)&addrCli, len);

if(res == -1)

{

perror("bind");

close(sockCli);

return -1;

}

res = connect(sockCli, (struct sockaddr*)&addrSer, len);

if(res == -1)

{

perror("connect");

close(sockCli);

return -1;

}

else

{

printf("Client Connect Server ok\n");

}

char sendbuf[BUF_SIZE];

char recvbuf[BUF_SIZE];

while(1)

{

connect(sockCli, (struct sockaddr*)&addrSer, len);

recv(sockCli, recvbuf, BUF_SIZE, 0);

printf("Ser :>%s\n", recvbuf);

printf("Cli :>");

scanf("%s", sendbuf);

if(strncmp(sendbuf, "quit", 4) == 0)

break;

send(sockCli, sendbuf, strlen(sendbuf)+1, 0);

}

close(sockCli);

return 0;}

(3)、運(yùn)行結(jié)果

6铜邮、UDP的編程實(shí)現(xiàn)

? 基礎(chǔ)的socket編程對(duì)UDP的就是下面的步驟:

(1)仪召、模型分析

(2)、代碼實(shí)現(xiàn)

utili.h

#include

#include

#include

#include

#include

#include

#define SERVER_PORT ?9090

#define SERVER_IP ? ?"127.0.0.1"

#define LISTEN_QUEUE ?5

#define BUFFER_SIZE ? 255

服務(wù)器端代碼:

#include"utili.h"

int main()

{

int sockSer = socket(AF_INET, SOCK_DGRAM, 0);

if(sockSer == -1)

{

perror("socket");

return -1;

}

struct sockaddr_in addrSer, addrCli;

addrSer.sin_family = AF_INET;

addrSer.sin_port = htons(SERVER_PORT);

addrSer.sin_addr.s_addr = inet_addr(SERVER_IP);

socklen_t len = sizeof(struct sockaddr);

int res = bind(sockSer, (struct sockaddr*)&addrSer, len);

if(res == -1)

{

perror("bind");

close(sockSer);

return -1;

}

char sendbuf[BUFFER_SIZE];

char recvbuf[BUFFER_SIZE];

while(1)

{

recvfrom(sockSer, recvbuf, BUFFER_SIZE, 0, (struct sockaddr*)&addrCli, &len);

printf("Cli:>%s\n",recvbuf);

printf("Ser:>");

scanf("%s",sendbuf);

if(strncmp(sendbuf, "quit", 4) == 0){

break;

}

sendto(sockSer, sendbuf, strlen(sendbuf)+1, 0, (struct sockaddr*)&addrCli, len);

}

close(sockSer);

return 0;}

客戶端代碼:

#include"utili.h"

int ?main()

{

int sockCli = socket(AF_INET, SOCK_DGRAM, 0);

if(sockCli == -1){

perror("socket");

return -1;

}

struct sockaddr_in addrSer;

addrSer.sin_family = AF_INET;

addrSer.sin_port = htons(SERVER_PORT);

addrSer.sin_addr.s_addr = inet_addr(SERVER_IP);

char sendbuf[BUFFER_SIZE];

char recvbuf[BUFFER_SIZE];

socklen_t ?len = sizeof(struct sockaddr);

while(1){

printf("Cli:>");

scanf("%s",sendbuf);

if(strncmp(sendbuf, "quit", 4) == 0){

break;

}

sendto(sockCli, sendbuf, strlen(sendbuf)+1, 0, (struct sockaddr*)&addrSer, len);

recvfrom(sockCli, recvbuf, BUFFER_SIZE, 0, (struct sockaddr*)&addrSer, &len);

printf("Ser:>%s\n",recvbuf);

}

close(sockCli);

return 0;

}

(3)松蒜、運(yùn)行結(jié)果

服務(wù)器端截圖

客戶端截圖

? 服務(wù)端的套接字總領(lǐng)全局扔茅,不與任何客戶端進(jìn)行通信,為每一個(gè)新的客戶端所分配一個(gè)新的套接字秸苗,進(jìn)行通信召娜。

? LISTEN_QUEUE:等待隊(duì)列的大小(最多等待多少隊(duì)列);

? UDP:必須先知道服務(wù)器在哪惊楼。

喜歡本文的朋友們玖瘸,歡迎長(zhǎng)按下圖關(guān)注訂閱號(hào)編程小兔崽,收看更多精彩內(nèi)容

每天進(jìn)步一點(diǎn)點(diǎn)檀咙,如果有用給小編點(diǎn)個(gè)贊

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末雅倒,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子弧可,更是在濱河造成了極大的恐慌屯断,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件侣诺,死亡現(xiàn)場(chǎng)離奇詭異殖演,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)年鸳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門趴久,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人搔确,你說(shuō)我怎么就攤上這事彼棍。” “怎么了膳算?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵座硕,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我涕蜂,道長(zhǎng)华匾,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任机隙,我火速辦了婚禮蜘拉,結(jié)果婚禮上萨西,老公的妹妹穿的比我還像新娘。我一直安慰自己旭旭,他們只是感情好谎脯,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著持寄,像睡著了一般源梭。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上稍味,一...
    開(kāi)封第一講書(shū)人閱讀 49,031評(píng)論 1 285
  • 那天废麻,我揣著相機(jī)與錄音,去河邊找鬼仲闽。 笑死,一個(gè)胖子當(dāng)著我的面吹牛僵朗,可吹牛的內(nèi)容都是我干的赖欣。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼验庙,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼顶吮!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起粪薛,我...
    開(kāi)封第一講書(shū)人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤悴了,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后违寿,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體湃交,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年藤巢,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了搞莺。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡掂咒,死狀恐怖才沧,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情绍刮,我是刑警寧澤温圆,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站孩革,受9級(jí)特大地震影響岁歉,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜膝蜈,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一刨裆、第九天 我趴在偏房一處隱蔽的房頂上張望澈圈。 院中可真熱鬧,春花似錦帆啃、人聲如沸瞬女。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)诽偷。三九已至,卻和暖如春疯坤,著一層夾襖步出監(jiān)牢的瞬間报慕,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工压怠, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留眠冈,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓菌瘫,卻偏偏與公主長(zhǎng)得像蜗顽,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子雨让,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容