Linux程式設計基礎 Socket程式設計

2021-09-06 07:57:53 字數 4198 閱讀 7803

linux下的socket程式設計大體上包括tcp socket、udp socket即raw socket這三種,其中tcp和udp方式的socket程式設計用於編寫應用層的socket程式,是我們用得比較多的,而raw socket則用得相對較少,不在本文介紹範圍之列。

tcp socket

基於tcp協議的客戶端/伺服器程式的一般流程一般如下:

它基本上可以分為三個部分:

一、建立連線:

伺服器呼叫

socket()

、bind()

、listen()

完成初始化後,呼叫

accept()

阻塞等待,處於監聽埠的狀態

客戶端呼叫socket()初始化後,呼叫connect()發出syn段並阻塞等待伺服器應答

伺服器應答乙個

syn-ack

段,客戶端收到後從

connect()

返回,同時應答乙個

ack段,伺服器收到後從

accept()

返回。

二、傳輸資料:

建立連線後,tcp協議提供全雙工的通訊管道,伺服器端和客戶端根據協議可以通過read和write的反覆呼叫實現資料的傳輸

三、關閉連線:

當資料傳輸已經完成後,伺服器和客戶端可以呼叫close關閉連線,一端關閉連線後,另一端read函式則會返回0,可以根據這個特徵來感應另一端的退出。

下面就以乙個簡單的echoserver演示一下如何建立伺服器端和客戶端**,其中和socket相關api都會高亮顯示。

伺服器端示例:

#include

#include

#include

#include

#include

#include

#include

#definemaxline 80

#defineserv_port 8000

intmain(void)

;servaddr.sin_family = af_inet;

servaddr.sin_addr.s_addr = htonl(inaddr_any);

servaddr.sin_port = htons(serv_port);

bind(listenfd, (sockaddr *)&servaddr, sizeof(servaddr));

listen(listenfd, 20);

printf("accepting connections ...\n");

while(1)

;socklen_t cliaddr_len = sizeof(cliaddr);

intconnfd =

accept(listenfd, (sockaddr *)&cliaddr, &cliaddr_len);

charstr[inet_addrstrlen];

printf("connected from %s at port %d\n",

inet_ntop(af_inet, &cliaddr.sin_addr, str, sizeof(str)),

ntohs(cliaddr.sin_port));

while(true)

close(connfd);

printf("closed from %s at port %d\n",

inet_ntop(af_inet, &cliaddr.sin_addr, str, sizeof(str)),

ntohs(cliaddr.sin_port));}}

ps:這裡需要注意的一下的是sock函式的第二個引數sock_stream,它表示是乙個tcp連線,後面我們會介紹通過傳入sock_dgram開啟udp連線。

伺服器端主體流程就是乙個死迴圈,它接受乙個socket連線,然後將其原封不動的返回給客戶端,待客戶端退出後,關閉socket連線,再次接受下乙個socket連線。

客戶端**如下:

#include

#include

#include

#include

#include

#include

#definemaxline 80

#defineserv_port 8000

#definemessage "hello world"

intmain(intargc, char*argv)

;servaddr.sin_family = af_inet;

inet_pton(af_inet, "127.0.0.1", &servaddr.sin_addr);

servaddr.sin_port = htons(serv_port);

if(0 !=

connect(sockfd, (sockaddr *)&servaddr, sizeof(servaddr)))

write(sockfd, message, sizeof(message));

intcount =

read(sockfd, buf, maxline);

printf("response from server: %s\n",buf);

close(sockfd);

return0;}

客戶端**比較簡單,這裡就不多介紹了。

udp socket

典型的udp客戶端/伺服器通訊過程如下圖所示:

由於udp不需要維護連線,程式邏輯簡單了很多,但是udp協議是不可靠的,實際上有很多保證通訊可靠性的機制需要在應用層實現,可能反而會需要更多**。

典型的示例如下:

/* server.cpp */

#include

#include

#include

#include

#definemaxline 80

#defineserv_port 8000

intmain(void)

;servaddr.sin_family = af_inet;

servaddr.sin_addr.s_addr = htonl(inaddr_any);

servaddr.sin_port = htons(serv_port);

bind

(sockfd, (sockaddr *)&servaddr, sizeof(servaddr));

printf("accepting connections ...\n");

while(1)

printf("received from %s at port %d\n",

inet_ntop(af_inet, &cliaddr.sin_addr, str, sizeof(str)),

ntohs(cliaddr.sin_port));

sendto

(sockfd, buf, count, 0, (sockaddr *)&cliaddr, sizeof(cliaddr));}}

/* client.cpp */

#include

#include

#include

#include

#include

#definemaxline 80

#defineserv_port 8000

intmain(intargc, char*argv)

;servaddr.sin_family = af_inet;

inet_pton(af_inet, "127.0.0.1", &servaddr.sin_addr);

servaddr.sin_port = htons(serv_port);

while(fgets(buf, maxline, stdin) != null)

count =

recvfrom

(sockfd, buf, maxline, 0, null, 0);

if(count == -1)

write(stdout_fileno, buf, count);

}close(sockfd);

return0;}

Linux基礎 socket程式設計詳解

在講socket程式設計之前,先來回顧一下tcp的三握手與四揮手過程,這樣就更易理解socket程式設計了。1.tcp三握手建立連線過程 2.tcp四揮手釋放連線過程 先來張圖,看看其過程如何 針對上圖出現的函式或其它重要的函式,我在此解釋下 1.socket 申請了乙個描述符 本地可見 但不能對外...

socket程式設計基礎

對於socket在這裡我不想究其歷史,我只想說其時它是一種程序通訊的方式,簡言之就是呼叫這個網路庫的一些api函式就能實現分布在不同主機的相關程序之間的資料交換.socket中首先我們要理解如下幾個定義概念 二是埠號 用來標識本地通訊程序,方便os提交資料.就是說程序指定了對方程序的網路ip,但這個...

socket程式設計基礎

對於socket在這裡我不想究其歷史,我只想說其時它是一種程序通訊的方式,簡言之就是呼叫這個網路庫的一些api函式就能實現分布在不同主機的相關程序之間的資料交換.socket中首先我們要理解如下幾個定義概念 二是埠號 用來標識本地通訊程序,方便os提交資料.就是說程序指定了對方程序的網路ip,但這個...