1. 程式人生 > >計算機網路_伺服器端只能處理一個客戶端_模型

計算機網路_伺服器端只能處理一個客戶端_模型

一、 需要知道

1.1 套接字

套接字是通訊端點的抽象。套接字描述符類似於檔案描述符。

accept recv阻塞執行

int listen(int sockfd, int size);  早期版本size含義是伺服器能維護的已完成的連線和正在連線的佇列的大小,有兩個佇列。新版本的含義是已完成的連線的佇列的大小。

1.2 通訊流程

圖1-1 伺服器端模型

圖1-2 客戶端模型

二、 伺服器端

#include<sys/socket.h>	//socket()  bind() listen() accept() 
#include<netinet/in.h>	//因特網地址結構
#include<string.h> //memset()
#include<stdio.h> //printf()
#include<arpa/inet.h> //inet_addr()
#include<assert.h> //assert()

int main()
{
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);   //建立套接字
    assert(-1 != sockfd);
    
    struct sockaddr_in ser, cli;    //套接字地址
    memset(&ser, 0, sizeof(ser));

    ser.sin_family = AF_INET;	//指定地址族 IPV4因特網域
    ser.sin_port = htons(6000);	//指定埠號 6000
    ser.sin_addr.s_addr = inet_addr("127.0.0.1");//指定伺服器ipv4地址

    //將套接字和地址關聯
    int res = bind(sockfd, (struct sockaddr*)&ser, sizeof(ser)); 
    assert(-1 != res);// 出錯原因 地址錯誤 埠號被佔用或者無權使用

    listen(sockfd, 5);	//願意接受5個連線請求    啟動監聽  並不具體處理 不阻塞!!!
    
    while(1) //迴圈處理客戶端請求
    {
	    int len = sizeof(cli);
	    int c = accept(sockfd, (struct sockaddr*)&cli, &len);
	    if(c < 0)
	    {
	        printf("error\n");
	        continue;
	    }
	    while(1) //迴圈接收客戶端輸入
	    {
	        char recvbuf[128] = {'\0'};
	        int n = recv(c, recvbuf, 127, 0); //有效位元組數最多為127
	        if(n <= 0)
	        {
	    	    printf("one client break\n");
		        break;
	        }
	        printf("%d: %s\n", c, recvbuf); //列印從客戶端獲取的輸入
	        send(c, "OK", 2, 0); //向客戶端傳送回執 提示符OK
	    }
	    close(c);   //關閉用於處理客戶端請求的套接字
    }
    close(sockfd); //關閉伺服器端
}

三、 客戶端

#include<sys/socket.h>	//socket()  bind() listen() accept() 
#include<netinet/in.h>	//因特網地址結構
#include<string.h> //memset()
#include<stdio.h> //printf()
#include<arpa/inet.h> //inet_addr()
#include<assert.h> //assert()

int main()
{
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    assert(-1 != sockfd);

    struct sockaddr_in ser, cli;
    memset(&ser, 0, sizeof(ser));

    ser.sin_family = AF_INET;
    ser.sin_port = htons(6000);
    ser.sin_addr.s_addr = inet_addr("127.0.0.1");
    int res = connect(sockfd, (struct sockaddr*)&ser, sizeof(ser)); //連線伺服器
    assert(-1 != res);
    
    while(1)
    {
	    printf("please imput: ");
	    fflush(stdout);
	    char buf[128] = {'\0'};
	    fgets(buf, 128, stdin);
	    buf[strlen(buf)-1] = '\0';  //覆蓋結尾的'\n'
	    if(0 == strncmp(buf, "end", 3)) //規定輸入end時,客戶端結束
	    {
	        break;
	    }
	    send(sockfd, buf, 127, 0); //傳送訊息
        
        //用於接收伺服器端的回執
	    char arr[3] = {'\0'};
	    recv(sockfd, arr, 2, 0);
	    printf("%s\n", arr);
    }
}

四、 執行結果

圖2 執行結果