1. 程式人生 > >linux環境下網路程式設計

linux環境下網路程式設計

 

參考

https://www.cnblogs.com/diligenceday/p/6241021.html

https://blog.csdn.net/baidu_36649389/article/details/79081770

http://www.cnblogs.com/wangcq/p/3520400.html

 

socket是網路程序的PID,由執行程序的計算機的IP地址和程序使用的埠組成。

非同步狀態下connect不阻塞,直接返回-1,connect返回-1是對的
然後通過select進行判斷是否連線上
同步狀態下connect阻塞,系統莫認時間75秒後,返回成功或失敗

TCP程式設計的流程

伺服器端

//
//  main.cpp
//  Server
//
//  Created by 藍貓 on 2018/12/13.
//  Copyright © 2018年 藍貓. All rights reserved.
//

#include <iostream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#define PORT 25555
#define BACK_LOG 20  //佇列允許請求數
#define BUF_SIZE 256 //  緩衝區大小
#define IP "192.168.1.5"
using std::cout;
using std::endl;

int main(int argc, const char * argv[])
{
    int ret;
    time_t tt;
    struct tm *ttm;
    char buf[BUF_SIZE];
    pid_t pid;//定義程序描述符
    int sockfd; //
    int clientfd;
    struct sockaddr_in host_addr;
    struct sockaddr_in client_addr;
    int length=sizeof(clientfd);
    sockfd=socket(AF_INET, SOCK_STREAM, 0);
    if(sockfd==-1)
    {
        cout<<"建立socket失敗"<<endl;
        exit(1);
    }
    bzero(&host_addr, sizeof(host_addr));
    host_addr.sin_family=AF_INET;//TCP/IP協議
    host_addr.sin_port=htons(PORT);//設定埠
    host_addr.sin_addr.s_addr=INADDR_ANY;//本地ip
    ret=bind(sockfd, (const struct sockaddr *)&host_addr, sizeof(host_addr));//繫結ip和埠
    if(ret==-1)
    {
        cout<<"bind失敗"<<endl;
        exit(1);
    }
    else
    {
        cout<<"bind成功"<<endl;
    }
    //監聽網路埠
    ret=listen(sockfd, BACK_LOG);
    if(ret==-1)
    {
        cout<<"監聽失敗"<<endl;
        exit(1);
    }
    while (1)
    {
        /*
          傾聽佇列之後 accept可以從傾聽套接字的完成佇列裡面接受一個連線,如果佇列是空,程序進入睡眠狀態。
         accept呼叫成功
         函式返回值是一個新的識別符號,標識接收的連線
         第二個引數描述客戶機地址 第三個描述客戶機地址長度
         */
        //clientfd=accept(sockfd, (struct sockaddr *)&client_addr, &length);//接收連線請求
        //clientfd=accept(sockfd, (struct sockaddr *)&client_addr,&length);
        clientfd = accept(sockfd, (struct sockaddr*)&client_addr, (socklen_t *)&length);
        if(clientfd==-1)
        {
            cout<<"接收失敗"<<endl;
            exit(1);
        }
        pid=fork();
        if(pid==0)
        {
            while (1)
            {
                bzero(buf, sizeof(buf));
                tt=time(NULL);
                ttm=localtime(&tt);//獲取當前時間引數
                strcpy(buf, asctime(ttm));// 將時間拷貝到緩衝區
                send(clientfd, buf, strlen(buf), 0);//傳送資料
                sleep(2);
            }
            close(clientfd);
        }
        else if(pid>0)
        {
            close(clientfd);//父程序關閉套接字 ,準備下一個客戶端連線
        }
    }
    return 0;
}

客戶端

//
//  main.cpp
//  Client
//
//  Created by 藍貓 on 2018/12/13.
//  Copyright © 2018年 藍貓. All rights reserved.
//
#include <iostream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#define PORT 25555
#define BACK_LOG 20  //佇列允許請求數
#define BUF_SIZE 256 //  緩衝區大小
#define IP "192.168.1.5"
using std::cout;
using std::endl;
int main(int argc, const char * argv[])
{
    int ret;
    char buf[BUF_SIZE];
    int sockfd;//套接字描述符
    struct sockaddr_in serv_addr;// 伺服器端的埠號和ip
    sockfd=socket(AF_INET, SOCK_STREAM, 0);
    if(sockfd==-1)
    {
        cout<<" socket建立失敗"<<endl;
        return 2;
    }
    bzero(&serv_addr, sizeof(serv_addr));
    serv_addr.sin_family=AF_INET;
    serv_addr.sin_port=htons(PORT);
    inet_aton(IP, (struct in_addr *)&serv_addr.sin_addr.s_addr);
    //serv_addr.sin_addr.s_addr=INADDR_ANY;
    cout<<"here1"<<endl;
    ret=connect(sockfd, (const struct sockaddr *)&serv_addr, sizeof(serv_addr));
    cout<<"here2"<<endl;
    if(ret==-1)
    {
        cout<<"connect失敗"<<endl;
        return 3;
    }
    else
    {
        cout<<"connect success"<<endl;
    }
    while (1)
    {
        bzero(buf, sizeof(buf));
        recv(sockfd, buf, sizeof(buf), 0);
        printf("接收到資料:%s",buf);
        sleep(1);
    }
    close(sockfd);
    return 0;
}

用多執行緒實現客戶端和伺服器端同時執行

//
//  main.cpp
//  多執行緒實現tcp c/s互動
//
//  Created by 藍貓 on 2018/12/14.
//  Copyright © 2018年 藍貓. All rights reserved.
//

#include <iostream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <pthread.h>
#define PORT 25554
#define BACK_LOG 20  //佇列允許請求數
#define BUF_SIZE 256 //  緩衝區大小
#define IP "192.168.1.5"
using std::cout;
using std::endl;

int server()
{
    int ret;
    time_t tt;
    struct tm *ttm;
    char buf[BUF_SIZE];
    pid_t pid;//定義程序描述符
    int sockfd; //
    int clientfd;
    struct sockaddr_in host_addr;
    struct sockaddr_in client_addr;
    int length=sizeof(clientfd);
    sockfd=socket(AF_INET, SOCK_STREAM, 0);
    if(sockfd==-1)
    {
        cout<<"伺服器:建立socket失敗"<<endl;
        exit(1);
    }
    bzero(&host_addr, sizeof(host_addr));
    host_addr.sin_family=AF_INET;//TCP/IP協議
    host_addr.sin_port=htons(PORT);//設定埠
    host_addr.sin_addr.s_addr=INADDR_ANY;//本地ip
    ret=bind(sockfd, (const struct sockaddr *)&host_addr, sizeof(host_addr));//繫結ip和埠
    if(ret==-1)
    {
        cout<<"伺服器:bind失敗"<<endl;
        exit(1);
    }
    else
    {
        cout<<"伺服器:bind成功"<<endl;
    }
    //監聽網路埠
    cout<<"伺服器:開始監聽"<<endl;
    ret=listen(sockfd, BACK_LOG);
    if(ret==-1)
    {
        cout<<"伺服器:監聽失敗"<<endl;
        exit(1);
    }
    while (1)
    {
        /*
         傾聽佇列之後 accept可以從傾聽套接字的完成佇列裡面接受一個連線,如果佇列是空,程序進入睡眠狀態。
         accept呼叫成功
         函式返回值是一個新的識別符號,標識接收的連線
         第二個引數描述客戶機地址 第三個描述客戶機地址長度
         */
        //clientfd=accept(sockfd, (struct sockaddr *)&client_addr, &length);//接收連線請求
        //clientfd=accept(sockfd, (struct sockaddr *)&client_addr,&length);
        cout<<"伺服器:準備接收"<<endl;
        clientfd = accept(sockfd, (struct sockaddr*)&client_addr, (socklen_t *)&length);
        if(clientfd==-1)
        {
            cout<<"伺服器:接收失敗"<<endl;
            exit(1);
        }
        pid=fork();
        if(pid==0)
        {
            while (1)
            {
                bzero(buf, sizeof(buf));
                tt=time(NULL);
                ttm=localtime(&tt);//獲取當前時間引數
                strcpy(buf, asctime(ttm));// 將時間拷貝到緩衝區
                send(clientfd, buf, strlen(buf), 0);//傳送資料
                sleep(2);
            }
            close(clientfd);
        }
        else if(pid>0)
        {
            close(clientfd);//父程序關閉套接字 ,準備下一個客戶端連線
        }
    }
    return 0;
}
int client()
{
    int ret;
    char buf[BUF_SIZE];
    int sockfd;//套接字描述符
    struct sockaddr_in serv_addr;// 伺服器端的埠號和ip
    sockfd=socket(AF_INET, SOCK_STREAM, 0);
    if(sockfd==-1)
    {
        cout<<" 客戶端:socket建立失敗"<<endl;
        return 2;
    }
    bzero(&serv_addr, sizeof(serv_addr));
    serv_addr.sin_family=AF_INET;
    serv_addr.sin_port=htons(PORT);
    //inet_aton(IP, (struct in_addr *)&serv_addr.sin_addr.s_addr);
    serv_addr.sin_addr.s_addr=INADDR_ANY;
    cout<<"客戶端:準備connect"<<endl;
    ret=connect(sockfd, (const struct sockaddr *)&serv_addr, sizeof(serv_addr));
    cout<<"客戶端:connect完成"<<endl;
    if(ret==-1)
    {
        cout<<"客戶端:connect失敗"<<endl;
        return 3;
    }
    else
    {
        cout<<"客戶端:connect success"<<endl;
    }
    while (1)
    {
        bzero(buf, sizeof(buf));
        recv(sockfd, buf, sizeof(buf), 0);
        printf("客戶端:接收到資料:%s",buf);
        sleep(1);
    }
    close(sockfd);
    return 0;
}
void *thread_server(void*arg)
{
    server();
    pthread_exit(NULL);
}
void *thread_client(void*arg)
{
    client();
    pthread_exit(NULL);
}
int main(int argc, const char * argv[])
{
    cout<<"開始"<<endl;
    pthread_t thread1,thread2;
    int ret;
    ret=pthread_create(&thread2, NULL, thread_client, NULL);
    if(ret!=0)
    {
        printf("client建立失敗\n");
        exit(1);
    }
    else
    {
        printf("client建立成功\n");
    }
    
    ret=pthread_create(&thread1, NULL, thread_server, NULL);
    if(ret!=0)
    {
        printf("server建立失敗\n");
        exit(1);
    }
    else
    {
        printf("server建立成功\n");
    }
    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);
    return 0;
}