Socket程式設計實踐 迭代回顯伺服器 UDP版

2021-08-20 12:13:05 字數 3828 閱讀 5188

建立socket套接字的api

函式原型

引數說明

繫結埠號的api

函式原型

引數說明

這個函式的第二個引數在傳參的時候,我們通常是定義乙個sockaddr_in型別的結構體,初始化後,強制型別轉換為sockaddr型別的。

sockaddr_in結構體成員說明:

struct sockaddr_in
成員說明:

1)sin_family和socket()的第乙個引數含義相同,取值也要保持一致。

2)uint16_t 的長度為兩個位元組,理論上埠號的取值範圍為0~65536,但是0~1023的埠一般由系統分配給特定的服務程式(稱為知名埠號),例如web服務的埠號為80,ftp服務的埠號為21,所以我們的程式使用的埠號一般要大於1023,小於65536。(埠號要用htos()函式轉換,hots()函式的作用是將本機位元組序轉換為網路位元組序)

3)sin_addr是struct in_addr結構體型別的變數。

struct in_addr
in_addr_t在標頭檔案< netinet/in.h >中定義,等價於unisgned long,長度為4個位元組,也就是說,s_addr是乙個整數,而ip位址是乙個字串,所以這個引數需要用inet_addr()函式進行轉換,eg:

unsigned long ip = inet_addr("127.0.0.1");

4)sin_zero[8]是多餘的8個位元組,一般用memset函式將結構體變數全置為0,給前三個成員複製後,第四個成員自然是0。

接收資料並儲存源位址的api

函式原型:

int recvfrom(socket s, char *buf, int len, int flags, \

struct sockaddr *from, int fromlen);

引數說明:

向指定目的地傳送資料的api

函式原型:

int sendto(socket s, const char *buf, int len, int flags, \

const struct sockaddr *to, int tolen);

引數說明:

業務邏輯:

1. 嘗試從socket中讀取客戶端傳送的請求

2. 讀取到請求後,根據請求內容,計算生成響應

3. 把響應寫回到socket中,再傳遞給客戶端

注意:客戶端不需要呼叫bind()繫結埠號,因為如果在同一臺機器上啟動多個客戶端,就容易出現埠號已經被占用導致不能成功建立連線的錯誤。

伺服器端如果不呼叫bind()繫結埠號,那麼核心就會自動給伺服器分配監聽埠,每次啟動伺服器時的埠號都不一樣,就會導致客戶端無法連線伺服器。

伺服器端**

#include

#include

#include

#include

#include

#include

#include

typedef

struct sockaddr sockaddr;

typedef

struct sockaddr_in sockaddr_in;

int main(int argc, char *argv)

//建立socket檔案

int socket = socket(af_inet,sock_dgram, 0);

if(socket < 0)

//繫結埠號

struct sockaddr_in addr;

addr.sin_family = af_inet;

addr.sin_addr.s_addr = inet_addr(argv[1]);

addr.sin_port = htons(atoi(argv[2]));

int ret = bind(sock, (sockaddr *)&addr, sizeof(addr));

if(ret < 0)

while(1);

//從socket中接收訊息

ssize read_size = recvfrom(sock, buf, sizeof(buf) - 1,\

0, (sockaddr*)*peer,&len);

if(read_size < 0)

buf[read_size] = '\0';

//將訊息列印到螢幕上

printf("[%s :%d] %s\n",inet_ntoa(peer.sin_addr), \

ntohs(peer,sin_port), buf);

//將訊息傳送回客戶端

sendto(sock, buf, strlen(buf), 0, \

(sockaddr*)&peer, sizeof(peer));

}close(sock);

return

0;}

客戶端**

#include

#include

#include

#include

#include

#include

#iclude

typedef

struct sockaddr sockaddr;

typedef

struct sockaddr_in sockaddr_in;

//通過命令列引數,指定客戶端向哪個伺服器傳送服務

int main(int argc, char *argv)

int sock = socket(af_inet, sock_dgram,0);

if(sock < 0)

sockaddr_in server_addr;

server_addr.sin_family = af_inet;

server_addr.sin_addr.s_addr = inet_addr(argc[1]);

server_addr,sin_port = htons(atoi(argv[2]));

while(1);

ssize_t read_size = read(0, buf, sizeof(buf) - 1);

if(read_size < 0)

if(read_size == 0)

buf[read_size] = '\0';

//2.把資料傳送給伺服器

sendto(socket, buf, strlen(buf), 0, \

(sockaddr*)&server_addr, sizeof(server_addr));

//3.嘗試從伺服器讀取資料

//此時revcfrom不需要知道對端的ip和埠號

//因為收到的資料一定是伺服器發回來的

//而伺服器對應的ip埠號已知

char buf_output[1024] = ;

read_size = recvfrom(sock, buf_output, \

sizeof(buf_output) - 1, 0, null, null);

//4.把讀取到的結果寫到標準輸出上

printf("server resp %s\n",buf_output);

}close(socket);

return

0;}

socket程式設計實踐

socket程式設計 1 函式說明。socket 程式設計的基本函式有 socket bind listen accept send sendto recv 以及 recvfrom 等,其中根據客戶端還是服務端,或者根據使用 tcp 協議還是 udp 協議,這些函式的呼叫流程都有所區別,這裡先對每個...

socket程式設計實踐

建立連線 1.1socket 非常類似於open函式,用來開啟乙個網路連線,如果成功則返回乙個網路檔案描述符 int型別 之後我們操作這個網路連線都通過這個網路檔案描述符 1.2bind繫結的意思 好比是ioctl 1.3listen監聽 1.4connect連線 客戶端 傳送和接收 2.1 sen...

五 socket實踐程式設計

1 伺服器端程式編寫 1 socket 2 bind 3 listen 4 accept,返回值是乙個fd,accept正確返回就表示我們已經和前來連線我的客戶端之間建立了乙個tcp連線了,以後我們就要通過這個連線來和客戶端進行讀寫操作,讀寫操作就需要乙個fd,這個fd就由accept來返回了。注意...