LinuxC/C++編程(10)—socket本地通信

直接貼代碼。

先介紹一下socket本地通信和網絡通信的不同之處:domain不一樣,sockaddr不一樣。

本地通信中,socket()的第一個參數爲AF_UNIX,sockaddr爲sockaddr_un(un代表UNIX)類型;

而網絡通信中,socket()的第一個參數爲AF_INET,sockaddr爲sockaddr_in(in代表INET)類型。

這是服務端:

//============================================================================
// Name        : localSocket.cpp
// Author      : Lin
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================

#include <iostream>
#include <sys/socket.h>
#include <unistd.h>
#include <cstdio>
#include <stdlib.h>
#include <sys/un.h>
#define BUFFER_SIZE 1024
#define MAX_QUEUE_NUM 5

using namespace std;


int main(int argc, char * argv[])
{
	unlink("/home/lin/桌面/test"); //先刪除socket文件,確保通信順利進行

	int socketFD;
	if ((socketFD = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
	{
		perror("create socket error:");
		exit(0);
	}

	int reuse = 0;
	if (setsockopt(socketFD, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
	{
		perror("set socket error");
		exit(0);
	}

	struct sockaddr_un name; //本地Socket地址,包含於<sys/un.h>,sockaddr_un對應於AF_UNIX這種通信方式
	name.sun_family = AF_UNIX;
	strcpy(name.sun_path, "/home/lin/桌面/test");
	if (bind(socketFD, (struct sockaddr*)&name, SUN_LEN(&name)) < 0)
	{
		perror("bind error:");
		exit(1);
	}

	listen(socketFD, 5); //設定最大連接個數

	while (true)
	{
		cout << "Server waiting!" << endl;

		struct sockaddr_un clientName;
		int clientSocketFD;
		socklen_t clientNameLen;
		if ((clientSocketFD = accept(socketFD, (struct sockaddr*)&clientName, &clientNameLen)) < 0)
		{
			perror("accept client error:");
			exit(0);
		}

		//cout << "The server has connect to the client: " << clientName.sun_path << endl;

		char receiveMsg[BUFFER_SIZE] = "";
		int receiveLen = 0;
		//string str;

		if ((receiveLen = read(clientSocketFD, receiveMsg, BUFFER_SIZE)) <= 0)  //一次性讀取全部信息,然後斷開鏈接,等待下一個socket,如果不想斷開鏈接,則必須新建一個線程來處理來accept()
		{
			cerr << "Read error!" << endl;
			exit(0);
		}
		else
		{
			cout << "The server has received " << receiveLen << " bytes!" << endl;
			cout << "The server has received msg:" << receiveMsg << endl;
		}



		//serving = serve(clientSocketFD);
		close(clientSocketFD);
	}

	close(socketFD);

	unlink("/home/lin/桌面/test"); //最後刪除socket所用的文件,不要留下臨時文件

	return 0;

}

接下來是客戶端:

//============================================================================
// Name        : localSocketClient.cpp
// Author      : Lin
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================

#include <iostream>
#include <sys/un.h>
#include <sys/socket.h>
#include <unistd.h>
#include <cstdlib>
#include <cstdio>

using namespace std;

void sendMsg(int socketFD, const char *msg)
{
	//write(socketFD, &len, sizeof(len));
	write(socketFD, msg, strlen(msg));
	cout << "The client has send the " << strlen(msg) << " bytes msg: " << msg << endl;
}

int main(int argc, char *argv[])
{
	const char* const socketName = "/home/lin/桌面/test";
	const char *const msg = argv[1];
	int socketFD;
	struct sockaddr_un name;

	if ((socketFD = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0)
	{
		perror("socket error:");
		exit(0);
	}

	name.sun_family = AF_LOCAL;
	strcpy(name.sun_path, "/home/lin/桌面/test");

	if (connect(socketFD, (struct sockaddr*)&name, sizeof(name)) < 0)
	{
		perror("connect fail:");
		exit(0);
	}

	sendMsg(socketFD, msg);
	close(socketFD);

	return 0;
}

測試方法:

各自編譯,先執行服務端程序:

lin@lin-Z97-HD3:~/workspace/localSocketServer/Debug$ ./localSocketServer

再同時開啓兩個客戶端程序:

lin@lin-Z97-HD3:~/workspace/localSocketClient/Debug$ ./localSocketClient heiheihei & ./localSocketClient 123

 在服務器對應的shell下可以看到輸出了正確的結果:

Server waiting!
The server has received 3 bytes!
The server has received msg:123
Server waiting!
The server has received 9 bytes!
The server has received msg:heiheihei
Server waiting!

最後用CTRL+C直接關掉服務器程序即可。代碼很簡單,有空再更新原理。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章