網(wǎng)絡(luò)編程

select函數(shù)實現(xiàn)多任務的用戶操作,回彈信息。。

// 回射服務器客戶端
// 從鍵盤讀入數(shù)據(jù),將讀入的數(shù)據(jù)發(fā)送給服務器,然后接收服務器回彈的數(shù)據(jù)
// 服務器的IP和端口從服務器讀入
// ./echo_client <server_ip> <server_port>

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>

#define N 200

int main(int argc, char *argv[])
{
    if(argc != 3)
    {
        printf("usage : %s <server_ip> <server_port>\n", argv[0]);
        return 1;
    }

    char buf[N] = {'\0'};
    int n = 0;
    
    // 1.socket
    int sock_fd = socket(AF_INET, SOCK_STREAM, 0);
    
    // 2.connect
    struct sockaddr_in serveraddr;
    
    memset(&serveraddr, 0, sizeof(serveraddr));
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
    serveraddr.sin_port = htons(atoi(argv[2]));
    if(connect(sock_fd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) == -1)
    {
        perror("connect failed");
        return 1;
    }
    
    // 3.read/write
    // 循環(huán)從鍵盤讀入數(shù)據(jù),發(fā)送給服務器端,當輸入.exit時,客戶端退出
    while(1)
    {
        // 3.1從鍵盤讀入數(shù)據(jù)
        write(STDOUT_FILENO, ">", 1);
        n = read(STDIN_FILENO, buf, N);
        
        // 3.2將讀入的數(shù)據(jù)發(fā)送給服務器
        // ssize_t send(int sockfd, const void *buf, size_t len, int flags);
        // 參數(shù):
        // sockfd   使用sockfd所關(guān)聯(lián)的套接字發(fā)送數(shù)據(jù)
        // buf      待發(fā)送數(shù)據(jù)的起始地址
        // len      待發(fā)送數(shù)據(jù)的字節(jié)長度
        // flags    發(fā)送方式
        // 返回值:實際發(fā)送成功的字節(jié)數(shù)
        send(sock_fd, buf, n, 0);
        
        // 當從鍵盤讀入的數(shù)據(jù)為.exit時,客戶端退出
        if(strncmp(buf, ".exit", 5) == 0)
            break;

        // 3.3接收從服務器回彈的數(shù)據(jù)病打印
        // ssize_t recv(int sockfd, void *buf, size_t len, int flags);
        // 參數(shù):
        // sockfd   從sockfd所關(guān)聯(lián)的套接字中接收數(shù)據(jù)
        // buf      存放接收數(shù)據(jù)的空間的起始地址
        // len      存放空間的最大字節(jié)數(shù)
        // flags    接收方式
        n = recv(sock_fd, buf, N, 0);
        printf("echo from server : \n");
        write(STDOUT_FILENO, buf, n);
    }
    
    printf("client exit, bye!!!\n");
    
    // close
    close(sock_fd);
    return 0;
}

// void FD_CLR(int fd, fd_set *set);
// 將參數(shù)fd所關(guān)聯(lián)的文件描述符從參數(shù)set集合中清楚

//int  FD_ISSET(int fd, fd_set *set);
// 判斷fd文件描述符是否在參數(shù)set集合中

//void FD_SET(int fd, fd_set *set);
// 將參數(shù)fd文件描述符加入到set集合中

//void FD_ZERO(fd_set *set);
// 清空集合set

// int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
// 參數(shù):
// nfds :   三個集合中最大文件描述符+1
// readfds :    讀集合
// writefds :   寫集合
// exceptfds :  異常集合
// timeout :    超時時間

// 使用select函數(shù)為TPC服務器添加主動退出功能
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/select.h>
#include <string.h>
#include <stdlib.h>

#define N 100

int main(int arc, char *argv[])
{
    int sock_fd = 0;
    struct sockaddr_in serveraddr;
    struct sockaddr_in clientaddr;
    socklen_t len = 0;
    int conn_fd = 0;
    char buf[N] = {'\0'};
    int i = 0;
    int j = 0;

    // 1.socket     SOCK_STREAM
    sock_fd = socket(AF_INET, SOCK_STREAM, 0);
    
    // 2.bind
    memset(&serveraddr, 0, sizeof(serveraddr));
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_addr.s_addr = inet_addr("10.211.55.3");
    //serveraddr.sin_addr.s_addr = INADDR_ANY;
    serveraddr.sin_port = htons(8888);
    if(bind(sock_fd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) == -1)
    {
        perror("bind failed");
        return 1;
    }
    
    // 3.listen
    listen(sock_fd, 15);
    
    // 使用select函數(shù)同時監(jiān)控標準輸入文件和監(jiān)聽套接字的使用
    // 1)創(chuàng)建文件描述符集合
    fd_set readfds;
    fd_set tmpfds;
    int max_fd = 0;
    FD_ZERO(&readfds);
    
    // 2)將需要被監(jiān)控的描述符添加到集合中
    FD_SET(STDIN_FILENO, &readfds);
    FD_SET(sock_fd, &readfds);
    max_fd = STDIN_FILENO>sock_fd?STDIN_FILENO:sock_fd;
    
    // 3)調(diào)用select函數(shù)篩選數(shù)據(jù)就緒的文件描述符
    while(1) 
    {
        tmpfds = readfds;
        // select函數(shù)的功能為將提供的集合中數(shù)據(jù)就緒的留下
        select(max_fd+1, &tmpfds, NULL, NULL, NULL);
        
        // 4)根據(jù)文件描述符是否在篩選后的集合中,來執(zhí)行相應操作
        for(i = 0; i < max_fd+1; i++)
        {
            if(!FD_ISSET(i, &tmpfds))
                continue;
                
            if(i == STDIN_FILENO)
            {
                // 標準輸入文件就緒,處理數(shù)據(jù)讀入  
                fgets(buf, N, stdin);
                if(strncmp(buf, ".exit", 5) == 0)
                    exit(0);
            }else if(i == sock_fd)
            {
                // 監(jiān)聽套接字就緒,處理連接請求   
                // 4.recv data/send data
                memset(&clientaddr, 0, sizeof(clientaddr));
                len = sizeof(clientaddr);
                conn_fd = accept(sock_fd, (struct sockaddr *)&clientaddr, &len);
                printf("conection with %s : %d\n",
                    inet_ntoa(clientaddr.sin_addr),
                    ntohs(clientaddr.sin_port));
    
                // 將新建的連接套接字加入到readfds中
                FD_SET(conn_fd, &readfds);
                // 更新max_fd
                if(conn_fd > max_fd)
                    max_fd = conn_fd;
            }
            else
            {
                // 某一個了連接套接字就緒
                // 接收客戶端發(fā)送來的數(shù)據(jù)并回彈
                recv(i, buf, N, 0);
                
                if(strncmp(buf, ".exit", 5) == 0)
                {
                    // 將該連接套接字從readfds中清除
                    FD_CLR(i, &readfds);
                    // 如果需要則更新max_fd
                    if(i == max_fd)
                    {
                        // 注意:以下寫法為C99標準支持
                        for(j = max_fd-1; j >= 0; j--)
                        {
                            if(FD_ISSET(j, &readfds))
                                break;
                        }
                        max_fd = j;
                    }
                    // 關(guān)閉該連接
                    close(i);
                }
                else
                {
                    send(i, buf, N, 0);
                }
            }
        }
    }
    
    // 6.close
    close(sock_fd);

    return 0;
}

1.會使用哪些容器,
2.數(shù)據(jù)庫的數(shù)據(jù)是怎么傳輸?shù)?br> 3.TCP和UDP的用處,具體怎么實現(xiàn)的
4.信號
5.鏈表
6.面向?qū)ο?br> 7.設(shè)計模式
8.你是做底層還是上層的
9.你是做前端還是后端的,

10.進程間通信方式,至少5種?
11.實時系統(tǒng)有哪幾種特性?
12.簡述一下三次握手
13.進程間通信同步方式有哪些
14.tcp/ip有幾層?具體講講數(shù)據(jù)鏈路層?
15.tcp/ip有幾次握手,幾次斷開?具體握手過程?
16.進通信有哪些?(具體講講信號量,具體講講消息隊列),
17.客戶端和服務器用的是進程還是線程,為什么?
18.多人聊天客戶端直接斷開了,服務器怎么解決?
19.多人聊天的時候有沒有考慮互斥等問題?

20.tcp和udp有什么區(qū)別
21,學過數(shù)據(jù)結(jié)構(gòu)嗎?
22,TCP四次分手中,主動關(guān)閉方最后為什么要等待MSL之后才關(guān)閉連接?
23,數(shù)據(jù)庫和服務器的連接方式
24.聊天系統(tǒng)太簡單了,一般公司不開發(fā)的,你們是要賣嗎?
25.說說TCP、UDP的區(qū)別?
26.寫一下并發(fā)性TCP偽代碼?
27.進程間的通信方式有哪些?區(qū)別?
28.寫一個服務器端的代碼?(簡單的)
29.寫一個客戶端的代碼?
30.Socket模型有select ,iocp,epoll三種,試著闡述原理,比較差異。

技術(shù)題:
1.面試他們會把你簡歷上你列出來的專業(yè)技能都會對你提問
2.基類,子類析構(gòu)順序
3.網(wǎng)絡(luò)模型

4.vector和list區(qū)別
5.malloc和new區(qū)別
6.繼承和組合區(qū)別
7.select里的enjoy
8.進程和線程的區(qū)別
9.你對面向?qū)ο笥卸嗌倭私?/p>

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容