C語言學習筆記-網絡與套接字

全部程序都須要編寫檢查錯誤的代碼linux

一.基礎知識服務器

客戶端與服務器之間將展開一段結構化對話,叫協議。網絡

在C語言中,若是寫一個與網絡通訊的程序,就須要新的數據流-套接字,套接字是雙向的,既能夠輸入也能夠輸出數據結構

1.使用socket()函數建立一個套接字數據流socket

#include <sys/socket.h>

int xxxx = socket(PF_INET, SOCK_STREAM, 0);

xxxx是套接字名字函數

套接字與客戶端程序通訊,服務器須要經歷,綁定端口,監聽,接受鏈接,開始通訊,四個階段spa

服務啓動時,服務器會爲每項服務分配一個端口,服務器啓動時,須要告訴操做系統將要使用哪一個端口,這個過程叫作端口綁定。操作系統

2.這些代碼將建立一個表示"互聯網xxx端口"的套接字名code

#include <arpa/inet.h>

struct sockeaddr_in xxxx;

xxxx.sin_family = PF_INET;

xxxx.sin+port = (in_port_t)htons(端口號);

xxxx.sin_addr.s_addr = htonl(INADDR_ANY);

int x = bind (套接字名字, (struct sockaddr * ) &xxxx, sizeof(name));

3.設置客戶端鏈接服務器的排隊數量blog

listen(套接字名字, xx)

xx爲人數

在linux操做系統的/etc/services文件中能夠查看經常使用服務使用的端口號

4.保存鏈接客戶端的詳細信息

struct sockaddr_storage xxxx;
unsigned int address_size = sizeof(client_addr);
int connect_d = accept(listener_d, (struct sockaddr *) &client_addr, &address_size);

套接字的輸出方法:

二.使用send()函數寫數據

send(套接字名稱, xxxx, strlen(xxx), 0)

xxx和strlen(xxx)是消息和消息長度

0是高級參數填0便可

綁定端口有延時的解決辦法,當使用某個端口綁定了套接字後,在接下來的30秒內,操做系統不容許任何程序綁定它,包括上次綁定這個端口的程序,咱們在綁定前設置套接字的某個選項,就能夠解決這個問題了。

int reuse = 1;

setsockopt(套接字名字, SQL_SOCKET, SO_REUSEADDR, (char * )&reuse, sizeof(int));

三.使用recv()函數讀數據

recv (接收的描述符,字符變量的緩衝區,<要讀取幾個字節>, 0);

1.字符串不以\0結尾

2.當用戶在客戶端輸入文本時用\r\n結尾

3.recv()將返回字符個數,若是發生錯誤就返回-1,若是客戶端關閉鏈接就返回0

4.recv調用不必定能一次接收全部字符,須要配合循環,讀取字符。

例如:

int read_in (int socket, char * buf, int len)

{

int c = recv(socket, buf, len, 0);

}

四.爲每一個客服端複製一份子進程

服務器在運行一份套接字進程給第一個用戶時,沒法運行第二個進程給第二個用戶,所以使用fork()爲每一個用戶建立一個子進程。

服務器父進程只須要用主監聽套接字,所以關閉副套接字,子進程需處理副套接字,關閉主監聽套接字

五.建立ip地址套接字

1.客戶端套接字的建立:

int xxx = socket (PF_INET, SOCK_STREAM, 0);

2.客戶端和服務器處理套接字的方法不一樣,服務器會把套接字綁定到本地端口,而客戶端會把套接字鏈接至遠程端口。

struct sockaddr_in xxx;

memset(&xxx, 0, sizeof(xxx));

xxx.sin_family = PF_INET;

xxx.sin_addr.s_addr = inet_addr("ip地址");

xxx.sin_port = htons(端口號);

connect(xxx, (struct sockaddr *) &xxx, sizeof(xxx)); 鏈接套接字至遠程端口

六.使用域名建立套接字

域名系統,計算機發送數據包時須要在地址一欄填寫數字形式的ip地址,而dns能夠把域名轉化爲ip地址

建立域名套接字:

#include<netdb.h>

struct addrinfo * xxx;

struct addrinfo xxxx;

memset(&xxxx, 0, sizeof(xxxx));

xxxx.ai_family = PF_UNSPEC;

xxxx.ai_socktype = SOCK_STREAM;

getaddrinfo("域名", "端口", &xxxx, &xxx);

getaddrinfo會在堆上建立一個xxx名字的新數據結構給定域名和端口號。

隨後建立套接字

int x = socket(xxx->ai_family, xxx->ai_socktype, xxx->ai_protocal);

connect(x, xxx->ai_addr, xxx->ai_addrlen);

freeaddrinfo(xxx);鏈接之後刪除地址數據
相關文章
相關標籤/搜索