socket程式設計實踐

2021-07-23 19:28:29 字數 3597 閱讀 9171

socket程式設計

(1)函式說明。

socket 程式設計的基本函式有 socket()、 bind()、 listen()、 accept()、 send()、 sendto()、 recv()以及 recvfrom()等,其中根據客戶端還是服務端,或者根據使用 tcp 協議還是 udp 協議,這些函式的呼叫流程都有所區別,這裡先對每個函式進行說明,再給出各種情況下使用的流程圖。

socket():該函式用於建立乙個 socket 連線,可指定 socket 型別等資訊。在建立了 socket 連線之後,可對 sockaddr 或 sockaddr_in 結構進行初始化,以保

存所建立的 socket 位址資訊。

bind():該函式是用於將本地 ip 位址繫結到埠號, 若繫結其他 ip 位址則不能成功。另外,它主要用於 tcp 的連線,而在 udp 的連線中則無必要。

listen():在服務端程式成功建立套接字和與位址進行繫結之後,還需要準備在該套接字上接收新的連線請求。此時呼叫 listen()函式來建立乙個等待佇列,在其中存放未處理的客戶端連線請求。

accept():服務端程式呼叫 listen()函式建立等待佇列之後,呼叫 accept()函式等待並接收客戶端的連線請求。它通常從由 bind()所建立的等待佇列中取出第乙個未處理的連線請求。

connect():該函式在 tcp 中是用於 bind()的之後的 client 端,用於與伺服器端建立連線,而在 udp 中由於沒有了 bind()函式,因此用 connect()有點類似 bind()函式的作用。

send()和 recv():這兩個函式分別用於傳送和接收資料,可以用在 tcp 中,也可以用在 udp 中。當用在 udp 時,可以在 connect()函式建立連線之後再用。

sendto()和 recvfrom():這兩個函式的作用與 send()和 recv()函式類似,也可以用在 tcp 和 udp 中。 當用在 tcp 時, 後面的幾個與位址有關引數不起作用,函式作用等同於 send()和 recv();當用在 udp 時,可以用在之前沒有使用connect()的情況下,這兩個函式可以自動尋找指定位址並進行連線。

(2)程式設計例項

該例項分為客戶端和伺服器端兩部分,其中伺服器端首先建立起 socket,然後與本地埠進行繫結, 接著就開始接收從客戶端的連線請求並建立與它的連線, 接下來,接收客戶端傳送的訊息。客戶端則在建立 socket 之後呼叫 connect()函式來建立連線。

伺服器端**:

#include #include #include #include #include #include #include #include #define port               4321 

#define buffer_size 1024

#define max_que_conn_nm 5

int main()

printf("socket id = %d\n",sockfd);

/*設定 sockaddr_in 結構體中相關引數*/

server_sockaddr.sin_family = af_inet;

server_sockaddr.sin_port = htons(port);

server_sockaddr.sin_addr.s_addr = inaddr_any;

bzero(&(server_sockaddr.sin_zero), 8);

int i = 1;/* 允許重複使用本地位址與套接字進行繫結 */

setsockopt(sockfd, sol_socket, so_reuseaddr, &i, sizeof(i));

/*繫結函式 bind()*/

if (bind(sockfd, (struct sockaddr *)&server_sockaddr,

sizeof(struct sockaddr)) == -1)

printf("bind success!\n");

/*呼叫 listen()函式,建立未處理請求的佇列*/

if (listen(sockfd, max_que_conn_nm) == -1)

printf("listening....\n");

/*呼叫 accept()函式,等待客戶端的連線*/

if ((client_fd = accept(sockfd,

(struct sockaddr *)&client_sockaddr, &sin_size)) == -1)

/*呼叫 recv()函式接收客戶端的請求*/

memset(buf , 0, sizeof(buf));

if ((recvbytes = recv(client_fd, buf, buffer_size, 0)) == -1)

printf("received a message: %s\n", buf);

close(sockfd);

exit(0);

}

客戶端**:

/*client.c*/ 

#include #include #include #include #include #include #include #include #define port 4321

#define buffer_size 1024

int main(int argc, char *argv)

/*位址解析函式*/

if ((host = gethostbyname(argv[1])) == null)

memset(buf, 0, sizeof(buf));

sprintf(buf, "%s", argv[2]);

/*建立 socket*/

if ((sockfd = socket(af_inet, sock_stream, 0)) == -1)

/*設定 sockaddr_in 結構體中相關引數*/

serv_addr.sin_family = af_inet;

serv_addr.sin_port = htons(port);

serv_addr.sin_addr = *((struct in_addr *)host->h_addr);

bzero(&(serv_addr.sin_zero), 8);

/*呼叫 connect 函式主動發起對伺服器端的連線*/

if(connect(sockfd,(struct sockaddr *)&serv_addr, sizeof(struct sockaddr))== -1)

/*傳送訊息給伺服器端*/

if ((sendbytes = send(sockfd, buf, strlen(buf), 0)) == -1)

close(sockfd);

exit(0);

}

在執行時需要先啟動伺服器端,再啟動客戶端。

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來返回了。注意...

socket實踐程式設計1

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