歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux技術 >> 在Ubuntu下實現本地套接字(socket)通信以及遇到的問題!

在Ubuntu下實現本地套接字(socket)通信以及遇到的問題!

日期:2017/3/3 15:16:20   编辑:Linux技術

客戶端:client.c

#include<stdio.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<sys/un.h>
#include<unistd.h>
#include<stdlib.h>

int main(){
	int sockfd;
	int len;
	struct sockaddr_un address;
	int result;
	char ch='A';

	sockfd=socket(AF_UNIX,SOCK_STREAM,0);
	address.sun_family=AF_UNIX;
	strcpy(address.sun_path,"server_socket");
	len=sizeof(address);
	
	result=connect(sockfd,(struct sockaddr *)&address,len);
	if(result==-1){
		perror("oops:client1");
		exit(1);
	}

	write(sockfd,&ch,1);
	read(sockfd,&ch,1);
	printf("char from server = %c \n",ch);
	close(sockfd);
	exit(0);
}
服務端:server.c

#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<sys/un.h>
#include<unistd.h>

int main(){
	int server_sockfd,client_sockfd;
	int server_len,client_len;
	struct sockaddr_un server_address;
	struct sockaddr_un client_address;

	<span >unlink("server_socket");// 創建本地套接字</span>
	server_sockfd=socket(AF_UNIX,SOCK_STREAM,0);

	server_address.sun_family=AF_UNIX;
	strcpy(server_address.sun_path,"server_socket");
	server_len=sizeof(server_address);
	bind(server_sockfd,(struct sockaddr *)&server_address,server_len);

	listen(server_sockfd,5);
	while(1){
		char ch;
		printf("server watting\n");
		
		client_len=sizeof(client_address);
		client_sockfd=accept(server_sockfd,
			(struct sockaddr *)&client_address,&client_len);
		
		read(client_sockfd,&ch,1);
		ch++;
		write(client_sockfd,&ch,1);
		close(client_sockfd);
	}
}
我在ubuntu下運行上述代碼時,它會報錯:找不到server_socket這個套接字,但同樣的代碼在centos下能運行,原來是我在ubuntu中運行程序的用戶不具有文件的讀寫權限。

所以我們需要把創建的套接字放在用戶都能訪問的 /tmp目錄下面(如下第一種方法)。

參考網址:http://blog.chinaunix.net/uid-26808060-id-4065810.html

socket進程通信命名方式有兩種:

一、普通的命名

socket會根據此命名創建一個同名的socket文件,客戶端連接的時候通過讀取該socket文件連接到socket服務端。這種方式的弊端是服務端必須對socket文件的路徑具備寫權限,客戶端必須知道socket文件路徑,且必須對該路徑有讀權限。

代碼實現:

server_address.sun_family = AF_UNIX;  
    strcpy(server_addr.sun_path,"/tmp/UNIX.domain");  
    server_len = sizeof(struct sockaddr_un);
二、抽象命名空間

這種方式不需要創建socket文件,只需要命名一個全局名字,即可讓客戶端根據此名字進行連接。後者的實現過程與前者的差別是,後者在對地址結構成員sun_path數組賦值的時候,必須把第一個字節置0,即sun_path[0] = 0

代碼實現:

server_addr.sun_family = AF_UNIX;  
    strcpy(server_addr.sun_path, SERVER_NAME);  
    server_addr.sun_path[0]=0;  
    //server_len = sizeof(server_addr);   
    server_len = strlen(SERVER_NAME)  + offsetof(struct sockaddr_un, sun_path);
其中,offsetof函數在#include 頭文件中定義。因第二種方式的首字節置0,我們可以在命名字符串SERVER_NAME前添加一個占位字符串,例如:

#define SERVER_NAME @socket_server
前面的@符號就表示占位符,不算為實際名稱。

Copyright © Linux教程網 All Rights Reserved