Socket

簡單介紹了套接字(Sockets)編程的基本概念

套接字(socket)作用

在任何通信中降铸,都有一個發(fā)送者和一個接收者啃匿,發(fā)送者和接收者是通信的兩端貌矿,也被稱為通信
的終端(communication endpoint), sockets是通信終端(communication endpoint)的一種抽
象,sockets設(shè)計用于網(wǎng)絡(luò)通信铺浇,網(wǎng)絡(luò)協(xié)議有很多種,這里主要以TCP協(xié)議為例介紹

套接字描述符(socket descriptor)

我們可以通過一個文件描述符(file descriptor)訪問文件垛膝,類似地鳍侣,我們也是通過套接字描
述符(socket descriptor)來訪問socket。不僅如此吼拥,在Unix中倚聚,socket descriptor就是
通過file descriptor實現(xiàn)的,對file descriptor的讀凿可、寫函數(shù)(read write)完全適用于
socket descriptor惑折。

不過相對于文件的讀寫,對socket的讀寫含義有小區(qū)別,讀一個socket就是讀取對方發(fā)送給
我們的數(shù)據(jù)唬复,寫一個socket就是向?qū)Ψ桨l(fā)送數(shù)據(jù)

創(chuàng)建套接字函數(shù)

#include <sys/socket.h>

int socket(int domain, int type, int protocol);
  • domain 表示通信的屬性矗积,包含通信地址格式全肮,POSIX中定義的取值有:AF_INET(ipv4)
    敞咧、AF_INET6(ipv6)、AF_UNIX(unix)辜腺、AF_UNSPEC(未指定)
  • type表示通信的類型休建,對于TCP通信,該字段為SOCKET_STREAM
  • protocol表示使用的通信協(xié)議

綁定通信地址

通信時需要綁定一個地址评疗,這樣不同的通信之間使用各自的地址测砂,互相干擾。綁定地址的時候
可以選擇使用系統(tǒng)自動分配的地址百匆,也可以手動綁定砌些。
在常見的客戶端和服務(wù)端通信模型中,客戶端可以讓使用系統(tǒng)自動分配的地址加匈,服務(wù)端則需要
顯示綁定一個地址存璃,這樣客戶端才能知道和哪個地址建立連接。
手動綁定地址的函數(shù)是:

#include <sys/socket.h>

int bind(int sockfd, const struct sockaddr *addr, socklen_t len);

建立連接

建立連接的三步驟

  1. 服務(wù)端就緒雕拼,等待客戶端的連接
#include <sys/socket.h>

int listen(int sockfd, int backlog);
  1. 客戶端請求建立連接
#include <sys/socket.h>

int connect(int sockfd, const struct sockaddr *addr, socklen_t len);
  1. 服務(wù)端接受連接
#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *restrict addr, socklen_t *restrict len);

讀寫數(shù)據(jù)

可以適用和讀寫文件一樣的函數(shù)纵东,也可以使用socket專有的

例子

  1. 服務(wù)端
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>

void error(const char *msg)
{
    perror(msg);
    exit(1);
}

int
main(int argc, char *argv[])
{
     socklen_t clilen;
     int n;
     //創(chuàng)建一個服務(wù)端的socket
     int serverfd = socket(AF_INET, SOCK_STREAM, 0);
     if (serverfd < 0) 
        error("ERROR opening socket");
     //初始化服務(wù)端地址
     struct sockaddr_in serv_addr;
     bzero((char *) &serv_addr, sizeof(serv_addr));
     serv_addr.sin_family = AF_INET;
     serv_addr.sin_addr.s_addr = INADDR_ANY;
     //端口號使用9002
     serv_addr.sin_port = htons(9002);  
    //綁定服務(wù)端地址
     if (bind(serverfd, (struct sockaddr *) &serv_addr,
              sizeof(serv_addr)) < 0) 
              error("ERROR on binding");
     //等待客戶端連接
     listen(serverfd, 5);
     //客戶端地址
     struct sockaddr_in cli_addr;
     clilen = sizeof(cli_addr);
     //接受客戶端連接
     int clientfd = accept(serverfd, (struct sockaddr *) &cli_addr, &clilen);
     if (clientfd < 0) 
          error("ERROR on accept");
     char buffer[256] = {0};
     //讀取客戶端發(fā)送的信息
     n = read(clientfd, buffer, 255);
     if (n < 0) error("ERROR reading from socket");
     printf("Here is the message: %s\n",buffer);
     close(serverfd);
     close(clientfd);
     return 0; 
}
  1. 客戶端
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h> 

void error(const char *msg)
{
    perror(msg);
    exit(0);
}

int main(int argc, char *argv[])
{
    printf("client is start....\n");
    int n;

    //創(chuàng)建客戶端socket
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) 
        error("ERROR opening socket");
    //初始化服務(wù)端地址
    struct sockaddr_in serv_addr;
    bzero((char *) &serv_addr, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    serv_addr.sin_port = htons(9002);
    //請求建立連接
    if (connect(sockfd, (struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0) 
        error("ERROR connecting");
    printf("connect to server");
    //發(fā)送數(shù)據(jù)
    char buffer[256] = "hi~";
    n = write(sockfd,buffer,strlen(buffer));
    if (n < 0) 
         error("ERROR writing to socket");
    close(sockfd);
    return 0;
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市啥寇,隨后出現(xiàn)的幾起案子偎球,更是在濱河造成了極大的恐慌,老刑警劉巖辑甜,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件衰絮,死亡現(xiàn)場離奇詭異,居然都是意外死亡磷醋,警方通過查閱死者的電腦和手機猫牡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來子檀,“玉大人镊掖,你說我怎么就攤上這事」犹担” “怎么了亩进?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長缩歪。 經(jīng)常有香客問我归薛,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任主籍,我火速辦了婚禮习贫,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘千元。我一直安慰自己苫昌,他們只是感情好,可當我...
    茶點故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布幸海。 她就那樣靜靜地躺著祟身,像睡著了一般。 火紅的嫁衣襯著肌膚如雪物独。 梳的紋絲不亂的頭發(fā)上袜硫,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天,我揣著相機與錄音挡篓,去河邊找鬼婉陷。 笑死,一個胖子當著我的面吹牛官研,可吹牛的內(nèi)容都是我干的秽澳。 我是一名探鬼主播,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼阀参,長吁一口氣:“原來是場噩夢啊……” “哼肝集!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起蛛壳,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤杏瞻,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后衙荐,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體捞挥,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年忧吟,在試婚紗的時候發(fā)現(xiàn)自己被綠了砌函。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡溜族,死狀恐怖讹俊,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情煌抒,我是刑警寧澤仍劈,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站寡壮,受9級特大地震影響贩疙,放射性物質(zhì)發(fā)生泄漏讹弯。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一这溅、第九天 我趴在偏房一處隱蔽的房頂上張望组民。 院中可真熱鬧,春花似錦悲靴、人聲如沸臭胜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽庇楞。三九已至,卻和暖如春否纬,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蛋褥。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工临燃, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人烙心。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓膜廊,卻偏偏與公主長得像,于是被迫代替她去往敵國和親淫茵。 傳聞我的和親對象是個殘疾皇子爪瓜,可洞房花燭夜當晚...
    茶點故事閱讀 44,927評論 2 355