伺服器 客戶端簡單實現(初學網路程式設計)

2021-07-22 21:18:24 字數 4228 閱讀 2781

宣告,本文**摘自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 ...