宣告,本文**摘自linux核心
伺服器端的設計模式:
主要有:套接字初始化,套接字與埠的繫結,設定伺服器的偵聽鏈結,接受和傳送資料並進行資料處理及處理完畢關閉套接字。
客戶端的設計模式:
主要分為套接字初始化,連線伺服器,讀寫網路資料,並進行後續釋放資源處理。
這應該是網路程式設計最基本的框架。剛開始學習,只能從基本的開始。
linux中,每乙個應用層函式都會和核心相關的系統呼叫進行互動:
舉個例子:
初始化套接字int sock = socket(af_inet, sock_stream, 0); 它會呼叫系統呼叫函式sys_socket(af_inet, sock_stream, 0);此函式分兩個部分,第一生成socket結構,第二與檔案描述符繫結,將繫結的描述符傳遞給應用層。下面貼出原始碼可以看看:
asmlinkage long sys_socket(int family, int type, int protocol)
sock_create()根據使用者的domain指定的協議族,建立乙個核心socket結構繫結到當前程序上,其中type和使用者空間的設定相同。sock_map_fd()函式將socket結構與檔案描述符列表中的某個檔案繫結,之後操作可以查詢檔案描述符列表來對應核心的socket結構。
其他的過程也都是通過系統呼叫核心函式完成的。
bind()函式對套接字進行位址和埠的繫結,才能進行資料的傳送。
應用層與核心函式之間的關係:傳遞相應的引數給核心。
相應的核心**:
asmlinkage long sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen)
err = sock->ops->bind(sock, (struct sockaddr *)address, addrlen);
}sockfd_put(sock);
}
return err;
}
listen()函式,listen 需要維護乙個等待佇列。故要設定佇列的長度。
相應的核心**:
asmlinkage long sys_listen(int fd, int backlog)
err=sock->ops->listen(sock, backlog);
sockfd_put(sock);
}return err;
}
accept()函式:當伺服器成功處理客戶端請求連線時,會有兩個檔案描述符。老的檔案描述符表示正在監聽的socket,新產生的檔案描述符表示客戶端的連線。send()和recv()都是通過新的檔案描述符來進行資料收發的。
accept核心層**比較長
asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, int __user *upeer_addrlen)
err = move_addr_to_user(address, len, upeer_sockaddr, upeer_addrlen);
if (err
< 0)
goto out_release;
}/* file flags are not inherited via accept() unlike another oses. */
if ((err = sock_map_fd(newsock)) < 0)
goto out_release;
security_socket_post_accept(sock, newsock);
out_put:
sockfd_put(sock);
out:
return err;
out_release:
sock_release(newsock);
goto out_put;
}
accept內部會新建立乙個socket,並進行相應的設定,產生對應的檔案描述符。
客戶端connect()函式與核心函式之間的關係:
asmlinkage long sys_connect(int fd, struct sockaddr __user *uservaddr, int addrlen)
學習網路基礎程式設計,結合核心**實現,更好的理解資料傳輸過程和核心底層都進行了那些操作。
以下為典型的c/s網路程式設計模型:
/*
* serverdemo.c
* * created on: 2023年9月19日
* author: huwang
*/#include
#include
#include
#include
#include
#include
#include
#define port 8888
#define backlog 2
void process_conn_server( int s);
int main(int argc, char **argv)
bzero(&server_addr, sizeof(server_addr));
server_addr.sin_family = af_inet;
server_addr.sin_addr.s_addr = htonl(inaddr_any);
server_addr.sin_port = htons(port);
err = bind(ss, (struct sockaddr * )&server_addr, sizeof(server_addr));
if(err < 0)
err = listen(ss, backlog);
if(err < 0)
for( ; ; )
pid = fork();
if(pid == 0)else
}}void process_conn_server( int s)
sprintf(buffer, "%zd bytes altogeter\n", size);
write(s, buffer, strlen(buffer) + 1);
}}
/*
* clientdemo.c
* * created on: 2023年9月19日
* author: huwang
*/#include
#include
#include
#include
#include
#include
#include
#include
#define port 8888
int s;
void process_conn_client(int s);
static
void sig_handle(int sign);
int main(int argc, char **argv)
bzero(&server_addr, sizeof(server_addr));
server_addr.sin_family = af_inet;
server_addr.sin_addr.s_addr = htonl(inaddr_any);
server_addr.sin_port = htons(port);
inet_pton(af_inet, argv[1], &server_addr.sin_addr);
connect(s, (struct sockaddr*)&server_addr, sizeof(struct sockaddr));
process_conn_client(s);
close(s);
return0;}
void process_conn_client(int s)
}}static
void sig_handle(int sign)
else
if(sign == sigint)
close(s);
return;
}
我想在這個基礎上可以進行拓展。 實現簡單UDP伺服器客戶端模型
udp是無連線的,在資料的傳送之前不需要連線,只需要知道要發資料給誰,然後將資料發出即可,可以直接接收到其他人發來的資料,不必呼叫listen 和accept 函式。所以udp中建立好套接字後,就可以直接進行資料的傳輸。基於udp的接收和傳送函式 include include ssize t se...
python socket 實現伺服器 客戶端通訊
伺服器 usr env bin python coding utf 8 import socket server def server sock socket.socket socket.af inet,socket.sock stream sock.bind localhost 8000 sock...
Linux下Socket伺服器與客戶端程式設計
對於socket程式設計零基礎,同時也沒有在linux下程式設計的經驗,分享給和我一樣的朋友。伺服器接收客戶端多次傳過來訊息,同時返回給客戶端進行迴圈處理。伺服器得起乙個執行緒,處理客戶端傳過來的訊息,否則伺服器與客戶端只能通訊一次。客戶端 code include include include ...