国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Linux網(wǎng)絡(luò)編程——C++實(shí)現(xiàn)進(jìn)程間TCP/IP通信

這篇具有很好參考價值的文章主要介紹了Linux網(wǎng)絡(luò)編程——C++實(shí)現(xiàn)進(jìn)程間TCP/IP通信。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

一、函數(shù)說明

  • 地址接口

1、通用地址接口

struct sockaddr
{
    u_short sa_family;  //地址類型,IPV4,用宏AG_INET即可;2字節(jié);
    char sa_data[14];  //14字節(jié)的地址數(shù)據(jù);
};

共16字節(jié) = 2字節(jié)地址類型 + 14字節(jié)地址數(shù)據(jù)
2、自定義地址接口

struct sockaddr_in
{
    short int sin_family;  //地址族,IPv4,用宏AF_INET;
    unsigned short int sin_port;  //端口號,需要htons函數(shù)進(jìn)行字節(jié)序轉(zhuǎn)換;
    struct in_addr sin_addr;  //IP地址,需要inet_addr函數(shù)進(jìn)行轉(zhuǎn)換(點(diǎn)分字符串→數(shù)值),該成員本身也是一個結(jié)構(gòu)體;
    unsigned char sin_zero[8];  //8個字節(jié)填0;
};
  • 地址轉(zhuǎn)換

1、需要將點(diǎn)分字符串ip轉(zhuǎn)化為程序ip,使用inet_addr函數(shù):

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
//inet_addr需要包含以上三個頭文件;
 
struct sockaddr_in servaddr;  //先定義一個該種地址接口的結(jié)構(gòu)體變量;
servaddr.sin_addr.s_addr = inet_addr(argv[1]);

2、字節(jié)序轉(zhuǎn)換
地址接口配置中的端口需要字節(jié)序轉(zhuǎn)換,網(wǎng)絡(luò)規(guī)定使用大端字節(jié)序。

#include <arpa/inet.h>  //頭文件;
 
//從主機(jī)(h)發(fā)送到網(wǎng)絡(luò)(n):
// 把unsigned long類型從主機(jī)序轉(zhuǎn)換到網(wǎng)絡(luò)序
uint32_t htonl(uint32_t hostlong);
// 把unsigned short類型從主機(jī)序轉(zhuǎn)換到網(wǎng)絡(luò)序
uint16_t htons(uint16_t hostshort);  //最常用!
 
//從網(wǎng)絡(luò)(n)接收到主機(jī)(h):
// 把unsigned long類型從網(wǎng)絡(luò)序轉(zhuǎn)換到主機(jī)序
unit32_t ntohl(uint32_t netlong);
// 把unsigned short類型從網(wǎng)絡(luò)序轉(zhuǎn)換到主機(jī)序
unit16_t ntohs(uint16_t netshort);
  • 地址接口配置

1、socket:創(chuàng)建套接字

#include<sys/types.h>
#include<sys/socket.h>

int socket(int family, int type, int protocol);
參數(shù) 含義
family 協(xié)議族,對于IPV4用宏AF_INET;
type 套接字類型:①對于tcp協(xié)議用宏SOCK_STREAM;②對于udp協(xié)議,用宏SOCK_DGRAM;
protocol 指定為0即可;
返回值 成功:返回文件描述符;失敗:-1;

2、bind:綁定

#include<sys/types.h>
#include<sys/socket.h>

int bind(int sockfd, const struct sockaddr* servaddr, socklen_t addrlen);
參數(shù) 含義
sockfd 前面socket創(chuàng)建成功返回的套接字,即文件描述符;
servaddr 配置好的通用地址接口.配置好的地址接口,屬于struct sockaddr_in 類型,需要轉(zhuǎn)換成第一種通用地址接口;注意是socklen_t類型,可以提前定義一個socklen_t類型變量,然后讓其等于sizeof(servaddr)
addrlen 配合第二個參數(shù)共同確認(rèn)地址接口變量的內(nèi)容;
返回值 成功:0;失敗:-1;

3、地址接口初始化

bzero(&servaddr, sizeof(servaddr));  //將地址接口結(jié)構(gòu)體清空;
servaddr.sin_family = AF_INET;  //用宏AF_INET代表IPV4;
servaddr.sin_port = htons(8080);  //設(shè)置端口號(字節(jié)序轉(zhuǎn)換);
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);  //這個宏表示任意IP地址,因?yàn)榉?wù)器不限定來訪的客戶端IP;

4、listen:監(jiān)聽(服務(wù)端專用)

#include<sys/types.h>
#include<sys/socket.h>

int listen(int sockfd, int backlog)
參數(shù) 含義
sockfd socket創(chuàng)建套接字的返回值
backlog 服務(wù)器的監(jiān)聽長度,設(shè)置1024即可
返回值 成功:0;失?。?1

5、accept:服務(wù)端連接

#include<sys/types.h>
#include<sys/socket.h>

int accept(int sockfd, struct sockaddr* cliaddr, socklen_t * addrlen);
參數(shù) 含義
sockfd socket創(chuàng)建套接字的返回值
cliaddr 是一個輸出參數(shù),從accept帶回來的的地址接口(客戶端),屬于struct sockaddr_in 類型,需要轉(zhuǎn)換成第一種通用地址接口
addrlen 配合第二個參數(shù)共同確認(rèn)地址接口變量的內(nèi)容,取該變量的地址
返回值 成功:0;失敗:-1

6、connect:客戶端連接

#include<sys/types.h>
#include<sys/socket.h>

int connect(int sockfd, struct sockaddr* servaddr, socklen_t  addrlen);
參數(shù) 含義
sockfd socket創(chuàng)建套接字的返回值
servaddr 配置好的地址接口,屬于struct sockaddr_in 類型,需要轉(zhuǎn)換成第一種通用地址接口
addrlen 配合第二個參數(shù)共同確認(rèn)地址接口變量的內(nèi)容,注意不是地址,直接是該變量
返回值 成功:0;失?。?1
  • 收發(fā)數(shù)據(jù)
    1、read/write
    因?yàn)閟ocket返回的是文件描述符,因此也可以像文件一樣使用read/write函數(shù)進(jìn)行數(shù)據(jù)傳輸。
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>

int write(int connfd,  void* buff, size_t length);
int read(int connfd,  void* buff, size_t length);
參數(shù) 含義
sockfd socket創(chuàng)建套接字的返回值
buff 文件緩沖區(qū),一般使用數(shù)組
length 想要讀(收)、寫(發(fā))的字節(jié)數(shù),對于單獨(dú)數(shù)組:strlen(buff),對于結(jié)構(gòu)體數(shù)組:sizeof(node)
返回值 成功:>0,實(shí)際發(fā)或者收到的字節(jié)數(shù);0:遇到文件尾巴;失?。?1

2、send/recv

#include<sys/types.h>
#include<sys/socket.h>

size_t send(int connfd,  void* buff, size_t length, int flags);
size_t recv(int connfd,  void* buff, size_t length, int flags);

flags功能選項(xiàng):
① 0:等同于write、read;
② MSG_DONTROUTE:send用,表示不查詢路由表,在內(nèi)部局域網(wǎng)進(jìn)行通信;
③ MSG_OOB:接收或發(fā)送帶外數(shù)據(jù)(插隊(duì));
④ MSG_PEEK:read用,表示讀取時不刪除數(shù)據(jù);
⑤ MSG_WAITALL:等待所有數(shù)據(jù)(阻塞等待);
返回值 :
成功:>0,實(shí)際發(fā)或者收到的字節(jié)數(shù);
0:對方已經(jīng)下線;
失?。?1;

二、示例代碼

客戶端client.cpp:

#include <iostream>
#include <cstring>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
using namespace std;
#define SIZE 1024

void connectToServer(int &serverfd){
    char sendBuf[SIZE], recvBuf[SIZE];
    ssize_t sendRet, recvRet;

    while(1){
        // 發(fā)送數(shù)據(jù)及接收響應(yīng)
        cout << ">> ";
        cin >> sendBuf;
        while(sendBuf){
            sendRet = send(serverfd, sendBuf, sizeof(sendBuf), 0);
            if(strcmp(sendBuf, "$") == 0)
                break;
            if (sendRet == -1)
                cout << "Error sending data\n";
            else 
                cout << "Sent data: " << sendBuf << endl;

            cout << ">> ";
            cin >> sendBuf;
        }
        
        // 接收響應(yīng)及數(shù)據(jù)
        recvRet = recv(serverfd, recvBuf, sizeof(recvBuf), 0);
        while(recvRet > 0){
            recvBuf[recvRet] = '\0';
            if(strcmp(recvBuf, "$") == 0)
                break;
            cout << "Received data: " << recvBuf << endl;
            recvRet = recv(serverfd, recvBuf, sizeof(recvBuf), 0);
        }

        // 是否關(guān)閉連接
        cout << "Do you want to close connection? (y/n)";
        char c;
        while ((c = getchar()) != '\n' && c != EOF);
        cin >> sendBuf;
        while(strcmp(sendBuf, "y") !=0 && strcmp(sendBuf, "n") != 0){
            cout << "Wrong input! Please input a letter 'y' or 'n' : ";
            cin >> sendBuf;
        }
        sendRet = send(serverfd, sendBuf, sizeof(sendBuf), 0);
        if (sendRet == -1)
            cout << "Error sending data\n";
        if(strcmp(sendBuf, "y") == 0)
            break;
    }

    // 關(guān)閉套接字
    close(serverfd);
}

int main() {
    // 創(chuàng)建套接字
    int serverfd = socket(AF_INET, SOCK_STREAM, 0);
    if (serverfd == -1) {
        cerr << "Error creating socket\n";
        return 1;
    }

    // 連接到服務(wù)器
    sockaddr_in serverAddr;
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(8080); // 與服務(wù)器相同的端口號
    inet_pton(AF_INET, "127.0.0.1", &serverAddr.sin_addr); // 這里使用本地回環(huán)地址,如果服務(wù)器在另一臺機(jī)器上,請?zhí)鎿Q為服務(wù)器的IP地址

    if (connect(serverfd, reinterpret_cast<struct sockaddr*>(&serverAddr), sizeof(serverAddr)) != -1) {
        cout << serverfd << " : Connected successfully!" << endl;
        connectToServer(serverfd);
    } else {
        cerr << "Error connecting to server\n";
        close(serverfd);
        return 1;
    }

    return 0;
}

服務(wù)端server.cpp:文章來源地址http://www.zghlxwxcb.cn/news/detail-829363.html

  • 一對一通信
#include <iostream>
using namespace std;

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

void connectToClient(int &clientfd) {
	char recvBuf[SIZE]; // 接收緩沖區(qū)
	char sendBuf[SIZE]; // 發(fā)送緩沖區(qū)
	int recvRet, sendRet; // 接受反饋及發(fā)送反饋

	while (clientfd != -1) {
		// receive data
		recvRet = recv(clientfd, recvBuf, sizeof(recvBuf), 0);
		while(recvRet > 0) {
			recvBuf[recvRet] = '\0';
			if(strcmp(recvBuf, "$") == 0)
				break;
			cout << "recv data from client " << clientfd << ", data : " << recvBuf << endl;
			recvRet = recv(clientfd, recvBuf, sizeof(recvBuf), 0);
		}

		// send data 
		cout << clientfd << ">> ";
		cin >> sendBuf;
		while(sendBuf) {
			sendRet = send(clientfd, sendBuf, sizeof(sendBuf), 0);
			if (strcmp(sendBuf, "$") == 0)
				break;
			if (sendRet == -1)
				cout <<"send data error." << endl;
			else
				cout << "Sent data to client: " << sendBuf << endl;
			cout << clientfd << ">> ";
			cin >> sendBuf;
		}

		// 是否關(guān)閉連接
		recvRet = recv(clientfd, recvBuf, sizeof(recvBuf), 0);
		if (recvRet == -1)
			cout << "Error receiving data\n";
		else if(strcmp(recvBuf, "y") == 0) {
			cout << "Have closed connection " << clientfd << '.' << endl;
			close(clientfd);
			break;
		}
	}
}

int main() {
	// create socket
	int serverfd = socket(AF_INET, SOCK_STREAM, 0); // IPV4 + TCP
	if(-1 == serverfd) {
		printf("create socket error");
		return -1;
	}
	
	// bind port 
	struct sockaddr_in bindaddr;
	bindaddr.sin_family = AF_INET;
	bindaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	bindaddr.sin_port = htons(8080);
	if(-1 == bind(serverfd, (struct sockaddr *)&bindaddr, sizeof(bindaddr))) {
		cout << "bind error" <<  endl;
		return -1;
	}
	
	// start listen
	if (listen(serverfd, 1024) == -1) {
		printf("listem error");
		return -1;
	}

	while (1) {
		struct sockaddr_in clientaddr;
		socklen_t clientaddrlen = sizeof(clientaddr);
		
		// accept connection
		int clientfd = accept(serverfd, (struct sockaddr *)&clientaddr, &clientaddrlen);
		if(clientfd!= -1) {
			// 獲取客戶端的信息
			char cliIp[16];
			inet_ntop(AF_INET, &clientaddr.sin_addr.s_addr, cliIp, sizeof(cliIp));
			unsigned short cliPort = ntohs(clientaddr.sin_port);
			cout << "client ip is : " << cliIp << ", port is : " << cliPort << endl;
			connectToClient(clientfd);
		}
	}
	
	//close socket
	close(serverfd);
	return 0;
}

  • 一對多通信(多進(jìn)程)
#include <iostream>
using namespace std;

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

void connectToClient(int &clientfd) {
	char recvBuf[SIZE]; // 接收緩沖區(qū)
	char sendBuf[SIZE]; // 發(fā)送緩沖區(qū)
	int recvRet, sendRet; // 接受反饋及發(fā)送反饋

	while (clientfd != -1) {
		// receive data
		recvRet = recv(clientfd, recvBuf, sizeof(recvBuf), 0);
		while(recvRet > 0) {
			recvBuf[recvRet] = '\0';
			if(strcmp(recvBuf, "$") == 0)
				break;
			cout << "recv data from client " << clientfd << ", data : " << recvBuf << endl;
			recvRet = recv(clientfd, recvBuf, sizeof(recvBuf), 0);
		}

		// send data 
		cout << clientfd << ">> ";
		cin >> sendBuf;
		while(sendBuf) {
			sendRet = send(clientfd, sendBuf, sizeof(sendBuf), 0);
			if (strcmp(sendBuf, "$") == 0)
				break;
			if (sendRet == -1)
				cout <<"send data error." << endl;
			else
				cout << "Sent data to client: " << sendBuf << endl;
			cout << clientfd << ">> ";
			cin >> sendBuf;
		}

		// 是否關(guān)閉連接
		recvRet = recv(clientfd, recvBuf, sizeof(recvBuf), 0);
		if (recvRet == -1)
			cout << "Error receiving data\n";
		else if(strcmp(recvBuf, "y") == 0) {
			cout << "Have closed connection " << clientfd << '.' << endl;
			close(clientfd);
			break;
		}
	}
}

int main() {
	// create socket
	int serverfd = socket(AF_INET, SOCK_STREAM, 0); // IPV4 + TCP
	if(-1 == serverfd) {
		printf("create socket error");
		return -1;
	}
	
	// bind port 
	struct sockaddr_in bindaddr;
	bindaddr.sin_family = AF_INET;
	bindaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	bindaddr.sin_port = htons(8080);
	if(-1 == bind(serverfd, (struct sockaddr *)&bindaddr, sizeof(bindaddr))) {
		cout << "bind error" <<  endl;
		return -1;
	}
	
	// start listen
	if (listen(serverfd, 1024) == -1) {
		printf("listem error");
		return -1;
	}

	while (1) {
		struct sockaddr_in clientaddr;
		socklen_t clientaddrlen = sizeof(clientaddr);
		
		// accept connection
		int clientfd = accept(serverfd, (struct sockaddr *)&clientaddr, &clientaddrlen);
		if(clientfd!= -1) {
			// 獲取客戶端的信息
            char cliIp[16];
            inet_ntop(AF_INET, &clientaddr.sin_addr.s_addr, cliIp, sizeof(cliIp));
            unsigned short cliPort = ntohs(clientaddr.sin_port);
			cout << "client ip is : " << cliIp << ", port is : " << cliPort << endl;
			
			pid_t pid = fork();
			if(pid == 0) // 子進(jìn)程
				connectToClient(clientfd);
		}
	}
	
	//close socket
	close(serverfd);
	return 0;
}

到了這里,關(guān)于Linux網(wǎng)絡(luò)編程——C++實(shí)現(xiàn)進(jìn)程間TCP/IP通信的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包