网络编程之本地通信
来源:互联网 发布:php 关闭call stack 编辑:程序博客网 时间:2024/06/15 07:28
IPC通信即本地进程之间的通信。
先举个简单例子吧。
服务器端代码:
1/********************************************************************************* 2 * Copyright: (C) 2017 luliteng<852335815@qq.com> 3 * All rights reserved. 4 * 5 * Filename: server.c 6 * Description: This file 7 * 8 * Version: 1.0.0(06/05/2017) 9 * Author: luliteng <852335815@qq.com> 10 * ChangeLog: 1, Release initial version on "06/05/2017 07:42:35 AM" 11 * 12 ********************************************************************************/ 13 #include <stdio.h> 14 #include <stdlib.h> 15 #include <netinet/in.h> 16 #include <sys/socket.h> 17 #include <arpa/inet.h> 18 #include <string.h> 19 20 int main(int argc, char **argv)//参数个数,参数 21 { 22 int fd = socket(AF_INET, SOCK_STREAM, 0);//创建socket,fd为socket的返回值 23 if (fd == -1)//判断对错,错误输出-1 24 { 25 perror("socket"); 26 exit(-1); 27 } 28 struct sockaddr_in addr;//通信地址结构准备 29 addr.sin_family = AF_INET;//网络通信 30 31 addr.sin_port = htons(2222);//端口号 32 addr.sin_addr.s_addr = inet_addr("192.168.71.128");//ip地址 33 int res = bind(fd, (struct sockaddr*)&addr, sizeof(addr));//创建bind(),res为bind的返回值 34 if (res == -1) 35 { 36 perror("bind"); 37 exit(-1); 38 } 39 printf("bind ok\n");//连接成功打印出bind ok 40 listen(fd, 100);//监听队列 41 struct sockaddr_in from; 42 socklen_t len = sizeof(from);
43 int sockfd = accept(fd, (struct sockaddr*)&from, &len);//创建accept,from是取前面地址 44 printf("%s连接了\n", inet_ntoa(from.sin_addr)); 45 char buf[100] = {}; 46 res = read(sockfd, buf, sizeof(buf));//把读出来的东西存到buf里面 47 printf("读到了%d字节,内容:%s\n", res, buf); 48 close(sockfd); 49 close(fd); 50 return 0; 51 }
客户端代码:
1 /********************************************************************************* 2 * Copyright: (C) 2017 luliteng<852335815@qq.com> 3 * All rights reserved. 4 * 5 * Filename: server.c 6 * Description: This file 7 * 8 * Version: 1.0.0(06/04/2017) 9 * Author: luliteng <852335815@qq.com> 10 * ChangeLog: 1, Release initial version on "06/04/2017 09:22:31 PM" 11 * 12 ********************************************************************************/ 13 #include <stdio.h> 14 #include <stdlib.h> 15 #include <sys/socket.h> 16 #include <arpa/inet.h> 17 #include <netinet/in.h> 18 19 int main(int argc, char **argv) 20 { 21 int fd = socket(AF_INET, SOCK_STREAM, 0); 22 if (fd == -1) 23 { 24 perror("socket"); 25 exit(-1); 26 } 27 struct sockaddr_in addr; 28 addr.sin_family = AF_INET; 29 addr.sin_port = htons(2222); 30 addr.sin_addr.s_addr = inet_addr("10.154.216.80"); 31 int res = connect(fd, (struct sockaddr*)&addr, sizeof(addr)); 32 if (res == -1) 33 { 34 perror("connect"); 35 exit(-1); 36 } 37 printf("connect ok\n"); 38 write(fd, "hello", 5); 39 close(fd); 40 return 0; 41 }
网络编程的基本结构服务器端:
1、socket
2、准备我们的通信地址结构体
3、服务器端为bind
4、监听listen
5、等待客户端连接,函数accept,返回新的描述符用于读写交互,accept相当于阻塞函数
6、读写函数
7、关闭socket
代码中用到的函数:
1>
int socket(int domain, int type, int protocol)
函数返回一个整型的socket描述符,供后面的使用,其中参数:
domain:指明使用的协议族,值
AF_INET:用于网络通信
AF_UNIX:单一Unix系统中进程间通信
type: 指明socket类型,值
SOCK_STREAM:流式,面向连接的比特流,顺序、可靠、双向,用于TCP通信
SOCK_DGRAM: 数据报式,无连接的,定长、不可靠 UDP通信
protocol:由于指定了type,这里一般用“0”
一个socket的建立:
int fd = socket(AF_INET, SOCK_STREAM, 0)
==================
intsocket(int domain,int type, int protocol)
_________________________返回值:非负描述符 – 成功,-1 - 出错
其中:
family指明了协议族/域,通常AF_INET、AF_INET6、AF_LOCAL等;
type是套接口类型,主要SOCK_STREAM、SOCK_DGRAM、SOCK_RAW;
protocol一般取为0。成功时,返回一个小的非负整数值,与文件描述符类似。
2>
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
将socket和相应的IP地址、 端口绑定
sockfd: socket()返回的文件描述符
addr: 绑定的IP和端口
将socket和相应的IP地址、 端口绑定
sockfd: socket()返回的文件描述符
addr: 绑定的IP和端口
addrlen: addr的长度
3>
int listen(int sockfd, int backlog);
开始监听套接字
backlog 是未经过处理的连接请求队列可以容纳的最大数目。
即每一个连入请求都要进入一个连入请求队列,等待
listen 的程序调用accept()函数来接受这个连接。当系统还没有
调用accept()函数的时候,如果有很多连接,那么本地能够等待的最大数目就是backlog 的
即每一个连入请求都要进入一个连入请求队列,等待
listen 的程序调用accept()函数来接受这个连接。当系统还没有
调用accept()函数的时候,如果有很多连接,那么本地能够等待的最大数目就是backlog 的
数值。
4>
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
开始等待客户端连过来套接字
addr 和 addrlen 一般是NULL, 否则只允许addr指定的客户端连过来。
5>
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
连接指定的服务器, 其中addr指定连接服务器的IP和端口
6>
int close(int fd);
关闭socket
7>
int shutdown(int sockfd, int how);
半关闭socket
半关闭socket
how: SHUT_RD、 SHUT_WR、 SHUT_RDWR
a) SHUT_RD,关闭连接的读这一半,套接字中不再有数据可接收,而且套接字接收缓冲区中的现有数据都被丢弃,进程不能再对这样的套接字调用任何读函数。该套接字接收的来自对端的任何数据都被确认,然后悄然丢弃。
b) SHUT_WR,关闭连接的写这一半,当前留在套接字发送缓冲区的数据都将被发送掉,后跟TCP的正常连接终止序列,进程不能再对这样的套接字调用任何写函数。
c) SHUT_RDWR,连接的读半部与写半部都关闭。
若成功返回0,若出错返回-1
来个实例更深入理解IPC通信
服务器端:
1 /********************************************************************************* 2 * Copyright: (C) 2017 luliteng<luliteng@gmail.com> 3 * All rights reserved. 4 * 5 * Filename: fuwuqi1.c 6 * Description: This file 7 * 8 * Version: 1.0.0(2017年05月10日) 9 * Author: luliteng <luliteng@gmail.com> 10 * ChangeLog: 1, Release initial version on "2017年05月10日 15时58分15秒" 11 * 12 ********************************************************************************/ 13 #include <stdio.h> 14 #include <stdlib.h> 15 #include <sys/socket.h> 16 #include <netinet/in.h> 17 #include <string.h> 18 #include <time.h> 19 #include <arpa/inet.h> 20 #include <signal.h> 21 int fd; 22 void fa(int signo) //用一个信号正常关闭文件描述符 23 { 24 printf("服务器即将关闭!\n"); 25 sleep(2); 26 close(fd); 27 exit(0); 28 } 29 /* 30 void TIME() 31 { 32 time_t timep; 33 time(&timep); 34 printf("当前时间:%s", ctime(&timep)); 35 } 36 */ 37 void TIME() //一个现实当前时间的函数 38 { 39 char buf[100] = {}; 40 41 time_t cur_time = time(0); 42 43 struct tm* cur = localtime(&cur_time); 44 sprintf(buf, "%4d-%02d-%02d %02d:%02d:%02d", cur->tm_year+1900, cur->tm_mon+1, cur-> tm_mday, cur->tm_hour, cur->tm_min, cur- >tm_sec); 45 printf("当前时间:%s\n", buf); 46 } 47 int main(int argc, char **argv) 48 { 49 TIME(); 50 51 printf("请按ctrl+C退出服务器\n"); 52 53 signal(SIGINT, fa); //发送信号关闭文件描述符 54 fd = socket(AF_INET, SOCK_STREAM, 0); //socket 55 if (fd == -1) perror("socket"), exit(-1); 56 57 struct sockaddr_in addr; //定义一系列结构体 58 addr.sin_family = AF_INET; 59 60 addr.sin_port = htons(2222); 61 addr.sin_addr.s_addr = inet_addr("192.168.71.128"); 62 int reuse = 1; 63 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)); //避免地址冲突 64 int res = bind(fd, (struct sockaddr*)&addr, sizeof(addr)); //绑定 65 if (res == -1) perror("bind"), exit(-1); 66 printf("bind ok!\n"); 67 listen(fd, 100); //监听 68 while(1){ 69 struct sockaddr_in from; 70 socklen_t len = sizeof(from); 71 int newfd = accept(fd, (struct sockaddr*)&from, &len); //有客户连接,则返回新 的描述符 72 if (newfd == -1) perror("accept"), exit(-1); 73 printf("%s连接了\n", inet_ntoa(from.sin_addr)); 74 TIME(); 75 pid_t pid = fork(); //有客户来时,创建一个子进程来处理 76 if(!pid) 77 { 78 char buf[100] = {}; 79 while(1){ 80 res = read(newfd, buf, sizeof(buf)); //对新的描述符进行读写操作 81 TIME(); 82 printf("读到了%d个字节,内容是%s\n", res, buf); 83 if (res == -1) perror("read"), exit(-1); 84 else if(!res) break; 85 if (!strcmp(buf, "byebye")) //当客户输入相应字符时,可知客户端退出了 86 { 87 printf("%s退出了\n", inet_ntoa(from.sin_addr)); 88 break; 89 } 90 write(newfd, buf, strlen(buf)); 91 memset(buf, 0, strlen(buf)); //清空buf 92 } 93 close(newfd); //子进程关闭新的描述符 94 exit(0); 95 } 96 close(newfd); //父进程关闭新的描述符 97 } 98 // close(fd); 99 return 0;100 }客户端:
1 /********************************************************************************* 2 * Copyright: (C) 2017 luliteng<luliteng@gmail.com> 3 * All rights reserved. 4 * 5 * Filename: myclient.c 6 * Description: This file 7 * 8 * Version: 1.0.0(2017年05月10日) 9 * Author: luliteng <luliteng@gmail.com> 10 * ChangeLog: 1, Release initial version on "2017年05月10日 16时10分16秒" 11 * 12 ********************************************************************************/ 13 #include <stdio.h> 14 #include <stdlib.h> 15 #include <sys/socket.h> 16 #include <netinet/in.h> 17 #include <string.h> 18 #include <time.h> 19 #include <arpa/inet.h> 20 #include <time.h> 21 /* void TIME() 22 { 23 time_t timep; 24 time(&timep); 25 printf("当前时间:%s", ctime(&timep)); 26 } 27 */ 28 void TIME() //时间函数 29 { 30 char buf[100] = {}; 31 time_t cur_time = time(0); 32 struct tm* cur = localtime(&cur_time); 33 sprintf(buf, "%4d-%02d-%02d %02d:%02d:%02d", cur->tm_year+1900, cur->tm_mon+1, cur->tm_mday, cur->tm_hour, cur->tm_min, cur- >tm_sec); 34 printf("当前时间:%s\n", buf); 35 } 36 int main(int argc, char **argv) 37 { 38 int fd = socket(AF_INET, SOCK_STREAM, 0); //socket 39 if (fd == -1) perror("socket"), exit(-1); 40 struct sockaddr_in addr; //定义结构体相关内容 41 addr.sin_family = AF_INET; 42 addr.sin_port = htons(2222); 43 addr.sin_addr.s_addr = inet_addr("192.168.71.128"); 44 int res = connect(fd, (struct sockaddr*)&addr, sizeof(addr)); //连接服务器端 45 if (res == -1) perror("connect"), exit(-1); 46 printf("connect ok!\n"); 47 char buf[100] = {}; 48 char buf1[100] = {}; 49 while(1){ 50 TIME(); 51 printf("请输入聊天内容:\n"); 52 scanf("%s", buf); 53 write(fd, buf, strlen(buf)); 54 if (!strcmp(buf, "byebye")) break; //输入相应字符退出 55 int res = read(fd, buf1, strlen(buf1)); 56 if (res == -1) 57 { 58 perror("read"); 59 break; 60 } 61 printf("read:%s\n", buf1); 62 memset(buf, 0, strlen(buf)); 63 memset(buf1, 0, strlen(buf1)); 64 } 65 close(fd); 66 67 68 return 0; 69 } 70通过gcc编译这两个.c文件,没有错误之后 分别运行./a.out
本地通信就这样构建了,一边发,一边收!
阅读全文
0 0
- 网络编程之本地通信
- linux网络编程(本地通信, android)
- Linux学习(二十七):TCP/IP网络编程之本地通信
- 网络编程之TCP通信
- 网络通信之tcp编程
- java编程之网络通信
- 网络通信之Socket编程
- 网络编程之IPC通信
- 【Linux网络编程】广播、组播与本地网络通信
- 网络编程之简单网络通信
- 网络编程之简单网络通信
- Java网络编程之TCP网络通信
- Java网络编程之UDP网络通信
- 网络编程之基本通信函数
- 网络编程之线程池通信
- 转贴:Android网络编程之Http通信
- Android网络编程之Http通信
- Android 网络编程之 Http 通信
- AJAX——核心XMLHttpRequest对象
- OkHttpUtils的常规使用
- 日常练习代码
- Sybase与Oracle区别(部分)
- React.js 官网资料摘记:事件处理
- 网络编程之本地通信
- 今天到过年的天数
- 编程入门书籍整理
- c++ 关闭屏幕
- USB触摸屏的驱动
- 一文了解强化学习
- 基于.NET CORE微服务框架 -surging的介绍和简单示例 (开源)
- Android socket通信: 一问一答,一问多答客户端网络请求工具类的实现
- Java注解(Annotation)——1 知识