ubuntu系统 网络socket通信和本地sock通信(抽象命名方式和普通命名方式)
来源:互联网 发布:报名系统源码 编辑:程序博客网 时间:2024/06/05 18:34
编译环境:ubuntu14.04
对于网络通信可以使用网络socket进行通信,但是如果在同一个机器中的两个进程间,或一个进程的两个线程见,则可以使用本地socket进行通信.
这样做相比与网络socket的好处是,更稳定,更安全.
稳定:当时用socket网络通讯时,使用网络套接字.避免为黑客留下后门.安全
安全:一台机器,本地,相比与网络更安全,不会在网络通顺过程中被人截取数据.
本地socket通信(普通命名方式)
client程序:
//c_unix.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#define UNIX_DOMAIN "/tmp/UNIX.domain"
int main(void)
{
int connect_fd;
int ret;
char snd_buf[1024];
int i;
static struct sockaddr_un srv_addr;
//creat unix socket
connect_fd=socket(PF_UNIX,SOCK_STREAM,0);
if(connect_fd<0)
{
perror("cannot create communication socket");
return 1;
}
srv_addr.sun_family=AF_UNIX;
strcpy(srv_addr.sun_path,UNIX_DOMAIN);
//connect server
ret=connect(connect_fd,(struct sockaddr*)&srv_addr,sizeof(srv_addr));
if(ret==-1)
{
perror("cannot connect to the server");
close(connect_fd);
return 1;
}
memset(snd_buf,0,1024);
strcpy(snd_buf,"message from client\n");
//send info server
for(i=0;i<4;i++)
write(connect_fd,snd_buf,sizeof(snd_buf));
close(connect_fd);
return 0;
}
server端程序(普通命名方式)
//s_unix.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#define UNIX_DOMAIN "/tmp/UNIX.domain"
/*
socket第一个参数
#define AF_LOCAL PF_LOCAL ->Local to host (pipes and file-domain) UNIX 进程通信协议。
#define AF_UNIX PF_UNIX ->Old BSD name for PF_LOCAL.
详细解释:http://blog.csdn.net/lee244868149/article/details/43732025
头文件:#include <unistd.h>
定义函数:int unlink(const char * pathname);
函数说明:unlink()会删除参数pathname 指定的文件. 如果该文件名为最后连接点, 但有其他进程打开了此文件, 则在所有关于此文件的文件描述词皆关闭后才会删除. 如果参数pathname 为一符号连接, 则此连接会被删除。
返回值:成功则返回0, 失败返回-1, 错误原因存于errno
错误代码:
1、EROFS 文件存在于只读文件系统内。
2、EFAULT 参数pathname 指针超出可存取内存空间。
3、ENAMETOOLONG 参数pathname 太长。
4、ENOMEM 核心内存不足。
5、ELOOP 参数pathname 有过多符号连接问题。
6、EIO I/O 存取错误。
*/
int main(void)
{
socklen_t clt_addr_len;
int listen_fd;
int com_fd;
int ret;
int i;
static char recv_buf[1024];
socklen_t len;
struct sockaddr_un clt_addr;
struct sockaddr_un srv_addr;
listen_fd=socket(PF_UNIX,SOCK_STREAM,0); //创建套接字,此时第一个参数可以看上面注释
if(listen_fd<0)
{
perror("cannot create communication socket");
return 1;
}
//set server addr_param
srv_addr.sun_family=AF_UNIX;
strncpy(srv_addr.sun_path,UNIX_DOMAIN,sizeof(srv_addr.sun_path)-1);
unlink(UNIX_DOMAIN);
//bind sockfd & addr
ret=bind(listen_fd,(struct sockaddr*)&srv_addr,sizeof(srv_addr));
if(ret==-1)
{
perror("cannot bind server socket");
close(listen_fd);
unlink(UNIX_DOMAIN);
return 1;
}
//listen sockfd
ret=listen(listen_fd,1);
if(ret==-1)
{
perror("cannot listen the client connect request");
close(listen_fd);
unlink(UNIX_DOMAIN);
return 1;
}
//have connect request use accept
len=sizeof(clt_addr);
com_fd=accept(listen_fd,(struct sockaddr*)&clt_addr,&len);
if(com_fd<0)
{
perror("cannot accept client connect request");
close(listen_fd);
unlink(UNIX_DOMAIN);
return 1;
}
//read and printf sent client info
printf("\n=====info=====\n");
for(i=0;i<4;i++)
{
memset(recv_buf,0,1024);
int num=read(com_fd,recv_buf,sizeof(recv_buf));
printf("Message from client (%d)) :%s\n",num,recv_buf);
}
close(com_fd);
close(listen_fd);
unlink(UNIX_DOMAIN);
return 0;
}
普通命名方式会在本地产生文件,对于不想在本地产生文件的需求的话,可以使用抽象命名方式.
如下:
server代码:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <stdlib.h>
#include <sys/un.h>
#include <stddef.h> // 抽象命名方式
#define SERVER_NAME "@socket_server" //抽象命名方式
int main()
{
int sockfd,newfd,ret,recv_num = 0,recv_num_total=0;
int recv_num1 = 0;
char buf[50] = {0};
char buf1[50] = {0};
struct sockaddr_un server_addr;
remove(SERVER_NAME);/*不管有没有,先删除一下,否则如果该文件已经存在的的话,bind会失败。*/
memset(&server_addr,0,sizeof(server_addr));
server_addr.sun_family=AF_UNIX;
// strcpy(server_addr.sun_path,SERVER_NAME);
strcpy(server_addr.sun_path, SERVER_NAME); //抽象命名方式
server_addr.sun_path[0]=0;
int server_len = strlen(SERVER_NAME) + offsetof(struct sockaddr_un, sun_path);
sockfd=socket(AF_UNIX,SOCK_STREAM,0);
if (sockfd<0)
{
printf("调用socket函数建立socket描述符出错!\n");
exit(1);
}
printf("调用socket函数建立socket描述符成功!\n");
ret=bind(sockfd,(struct sockaddr *)(&server_addr), server_len);//sizeof(server_addr));
if (ret<0)
{
printf("调用bind函数绑定套接字与地址出错!\n");
exit(2);
}
printf("调用bind函数绑定套接字与地址成功!\n");
ret=listen(sockfd,4);
if (ret<0)
{
printf("调用listen函数出错,无法宣告服务器已经可以接受连接!\n");
exit(3);
}
printf("调用listen函数成功,宣告服务器已经可以接受连接请求!\n");
newfd=accept(sockfd,NULL,NULL);/*newfd连接到调用connect的客户端*/
if (newfd<0)
{
printf("调用accept函数出错,无法接受连接请求,建立连接失败!\n");
exit(4);
}
printf("调用accept函数成功,服务器与客户端建立连接成功!\n");
while (1)
{
recv_num=recv(newfd,buf,10,0);
recv_num1=recv(newfd,buf1,31,0);
if (recv_num<0)
printf("调用recv接受失败!\n");
else
{
recv_num_total+=recv_num;
//printf("调用recv函数成功,本次接受到%d个字节,内容为:%s。共受到%d个字节的数据。\n",recv_num,buf,recv_num_total);
printf("recv data0: %s. recv data len0 %d\n", buf, recv_num);
printf("recv data1: %s. recv data len1 %d", buf1, recv_num1);
}
sleep(2);
break;
}
}
client代码:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <stdlib.h>
#include <sys/un.h>
#include <stddef.h> // 抽象命名方式
#define SERVER_NAME "@socket_server" //抽象命名方式
/*
程序里包含服务端和客户端两个程序,它们之间使用 AF_UNIX 实现本机数据流通信。使用 AF_UNIX 域实际上是使用本地 socket 文件来通信。
*/
int main()
{
int sockfd,ret,send_num,send_num_total=0;
char buf[]="this is my socket data.11111111111111111";
printf("size:%d", (int)sizeof(buf));
struct sockaddr_un server_addr;
memset(&server_addr,0,sizeof(server_addr));
server_addr.sun_family=AF_UNIX;
// strcpy(server_addr.sun_path,"test.socket");
strcpy(server_addr.sun_path, SERVER_NAME); //抽象命名方式
server_addr.sun_path[0]=0;
int client_len = strlen(SERVER_NAME) + offsetof(struct sockaddr_un, sun_path);
sockfd=socket(AF_UNIX,SOCK_STREAM,0);
if (sockfd<0)
{
printf("调用socket函数建立socket描述符出错!\n");
exit(1);
}
printf("调用socket函数建立socket描述符成功!\n");
ret=connect(sockfd,(struct sockaddr *)(&server_addr),client_len);//sizeof(server_addr));
if (ret<0)
{
printf("调用connect函数失败,客户端连接服务器失败!\n ");
exit(2);
}
printf("调用connect函数成功,客户端连接服务器成功!\n");
while (1)
{
send_num=send(sockfd,buf,sizeof(buf),MSG_DONTWAIT);
if (send_num<0)
printf("调用send函数失败!");
else
{
send_num_total+=send_num;
printf("调用send函数成功,本次发送%d个字节,内容为:%s。目前共发送了%d个字节的数据。\n",send_num,buf,send_num_total);
}
sleep(2);
break;
}
}
关于网络socket通信,没有测试,仿照本地socket写即可,将参数换一下.提供参考如下
server代码:
#define LOCAL_ADDRESS "127.0.0.1"
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = inet_addr(LOCAL_ADDRESS);
server_address.sin_port = htons(6000);
server_len = sizeof(server_address);
s_cmd_server_sockfd = socket(AF_INET,SOCK_STREAM,0);
bind(s_cmd_server_sockfd,(struct sockaddr *)&server_address,server_len);
listen(s_cmd_server_sockfd,5);
printf("server waiting for connect\n");
client_len = sizeof(client_address);
s_cmd_client_sockfd = accept(s_cmd_server_sockfd,(struct sockaddr *)&client_address,(socklen_t *)&client_len);
printf("accept cmd serverId: %d, clientid: %d\n", s_cmd_server_sockfd, s_cmd_client_sockfd);
unsigned char buf[50];
// while (1) {
recv_num_cmd = recv(s_cmd_client_sockfd,buf,50,0);
if (recv_num_cmd<0)
printf("调用recv接受失败!\n");
else
{
recv_num_total_cmd += recv_num_cmd;
printf("cmd 调用recv函数成功,本次接受到%d个字节,内容为:\"%s\"。共受到%d个字节的数据。\n",recv_num_cmd,buf,recv_num_total_cmd);
}
sleep(2);
// }
client代码:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <string>
#include <string.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
int sockfd,send_num,send_num_total=0;
char buf[]="liushuanpeng.";
sockaddr_in m_addr;
int m_sock = socket ( AF_INET, SOCK_STREAM, 0 );
if (sockfd<0)
{
printf("调用socket函数建立socket描述符出错!\n");
exit(1);
}
printf("调用socket函数建立socket描述符成功!\n");
m_addr.sin_family = AF_INET;
m_addr.sin_port = htons ( 6000 );
int status = inet_pton ( AF_INET, "127.0.0.1"/*host.c_str()*/, &m_addr.sin_addr );
status = ::connect ( m_sock, ( sockaddr * ) &m_addr, sizeof ( m_addr ) );
if (status != 0)
{
printf("调用connect函数失败,客户端连接服务器失败!\n ");
exit(2);
}
printf("cmd 调用connect函数成功,客户端连接服务器成功!\n");
// while (1)
// {
//send_num=send(sockfd,buf,sizeof(buf),MSG_DONTWAIT);
send_num = ::send(m_sock, buf, 50, MSG_NOSIGNAL);
if (send_num<0)
printf("调用send函数失败!");
else
{
send_num_total+=send_num;
printf("cmd 调用send函数成功,本次发送%d个字节,内容为:\"%s\"。目前共发送了%d个字节的数据。\n",send_num,buf,send_num_total);
}
sleep(2);
// }
}
参考文章:
http://blog.csdn.net/shanzhizi/article/details/16882087
http://blog.csdn.net/shanzhizi/article/details/16882087
http://blog.csdn.net/qq_28839293/article/details/51276550
- ubuntu系统 网络socket通信和本地sock通信(抽象命名方式和普通命名方式)
- Socket本地通信和网络通信
- 命名管道的通信方式
- 【进程间通信】普通管道和命名管道(FIFO)
- Socket网络通信方式/模型
- C# socket通信TCP和UDP方式
- Linux进程间通信方式--本地socket
- Linux进程间通信方式--本地socket
- Linux进程间通信方式--本地socket
- Linux进程间通信方式--本地socket
- Linux进程间通信方式--本地socket
- Android系统Native和Framework通信方式
- 以命名管道方式实现网络进程间通信的一个实例
- 以命名管道方式实现网络进程间通信的一个实例
- Android 三种网络通信方式(Socket...)
- 进程通信:匿名管道和命名管道
- 线程通信方式同步方式和进程间通信方式.
- wince 通信方式 SOCKET
- Cloudera 配置NameNode HA
- Android如何获取SHA1
- openlayer 系列二(地图切换控件)
- 浅谈Android中的MVP
- 训练总结
- ubuntu系统 网络socket通信和本地sock通信(抽象命名方式和普通命名方式)
- 图书管理系统数据库设计
- python tempfile
- swing入门和布局管理
- Idea + Hadoop2.7.4开发Mapreduce
- bzoj 1786 && bzoj 1831: [Ahoi2008]Pair 配对(DP)
- 很不错的 app 更新
- 字符串的模拟
- 2017年11月总结