1>socket(套接字通信)
基于TCP服务器实现:
int main()
{//1、创建套接字,用于连接使用int sfd = socket(AF_INET, SOCK_STREAM, 0);if(sfd == -1){perror("socket error");return -1;}//设置端口号快速重用int reuse = 1;if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) == -1){perror("setsockopt error");return -1;}printf("端口快速重用成功\n");//2、给套接字绑定地址信息//2.1 填充地址信息结构体struct sockaddr_in sin;sin.sin_family = AF_INET; //地址族sin.sin_port = htons(PORT); //端口号网络字节序sin.sin_addr.s_addr = inet_addr(IP); //IP地址网络字节序//2.2 绑定工作if(bind(sfd, (struct sockaddr*)&sin, sizeof(sin)) == -1){perror("bind error");return -1;}printf("bind success _%d_\n", __LINE__);//3、将套接字设置成监听状态if(listen(sfd, 128) == -1){perror("listen error");return -1;}printf("listen success _%d_\n", __LINE__);//4、阻塞等待客户端的连接请求//4.1 填充要接收的客户端地址信息结构体struct sockaddr_in cin;cin.sin_family = AF_INET; //IPv4通信//客户端的主机地址和端口号就无需写了//4.2 定义接收客户端的地址信息的大小socklen_t socklen = sizeof(cin);//4.3 接收客户端的请求int newfd = accept(sfd, (struct sockaddr*)&cin, &socklen);if(newfd == -1){perror("accept error");return -1;}printf("有新客户端连接,newfd = %d\n", newfd);//5、收发数据char buf[128] = ""; //用于接收数据的缓冲区while(1){//清空缓冲区bzero(buf, sizeof(buf));int ret = recv(newfd, buf, sizeof(buf), 0);if(ret == -1){perror("recv error");return -1;}else if(ret == 0){printf("客户端已经下线\n");break;}printf("[%s:%d] :%s\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), buf);//将数据连接一个字符后发回去strcat(buf, "*_*");if(send(newfd, buf, sizeof(buf), 0) == -1){perror("send error");return -1;}}//6、关闭套接字close(newfd); //关闭通信的套接字close(sfd); //关闭连接的套接字return 0;
}
基于TCP客户端实现:
int main()
{//1、创建套接字,用于连接使用int cfd = socket(AF_INET, SOCK_STREAM, 0);if(cfd == -1){perror("socket error");return -1;}//设置端口号快速重用int reuse = 1;if(setsockopt(cfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) == -1){perror("setsockopt error");return -1;}printf("端口快速重用成功\n");//2、给套接字绑定地址信息//2.1 填充地址信息结构体struct sockaddr_in sin;sin.sin_family = AF_INET; //地址族sin.sin_port = htons(PORT); //端口号网络字节序sin.sin_addr.s_addr = inet_addr(IP); //IP地址网络字节序//2.2 绑定工作if(bind(cfd, (struct sockaddr*)&sin, sizeof(sin)) == -1){perror("bind error");return -1;}printf("bind success _%d_\n", __LINE__);//4、连接服务器//4.1 填充要连接的服务器地址信息结构体struct sockaddr_in cin;cin.sin_family = AF_INET; //IPv4通信cin.sin_port = htons(PORT); //服务器端口号cin.sin_addr.s_addr = inet_addr(IP); //服务器的主机地址//4.2 连接服务器if(connect(cfd, (struct sockaddr*)&cin, sizeof(cin)) == -1){perror("connect error");return -1;}printf("connect success _%d_\n", __LINE__);//5、收发数据char buf[128] = ""; //用于接收数据的缓冲区while(1){//清空缓冲区bzero(buf, sizeof(buf));//从终端上获取数据fgets(buf, sizeof(buf), stdin);buf[strlen(buf) -1] = '\0';//发送给服务器端if(send(cfd, buf, sizeof(buf), 0) == -1){perror("send error");return -1;}printf("发送成功\n");//接收服务器发来的消息bzero(buf, sizeof(buf));int res = recv(cfd, buf, sizeof(buf), 0);if(res == -1){perror("recv error");return -1;}else if(res == 0){printf("服务器已经下线\n");break;}printf("[%s:%d] :%s\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), buf);}//6、关闭套接字close(cfd); //关闭连接的套接字return 0;
}
2>无名管道
int main()
{//定义子进程的pidpid_t pid;//1、定义管道的文件描述符数组int pipefd[2] = {0};//2、创建管道if(pipe(pipefd) != 0){perror("pipe error");return -1;}//创建子进程pid = fork();if(pid < 0){perror("fork error");return -1;}else if(pid == 0){//关闭写管道close(pipefd[1]);//子进程char rbuf[128] = "";while(1){//清空容器内容memset(rbuf, 0, sizeof(rbuf));//读取父进程发送的消息read(pipefd[0], rbuf, sizeof(rbuf));printf("收到父进程消息:%s\n", rbuf);if(strcmp(rbuf, "quit") == 0){break;}}//关闭读管道close(pipefd[0]);//退出进程exit(0);}else{//关闭读管道close(pipefd[0]);//父进程char wbuf[128] = "";while(1){bzero(wbuf, sizeof(wbuf)); //清空容器内容// printf("请输入>>");fgets(wbuf, sizeof(wbuf), stdin); //从终端读取一个字符串wbuf[strlen(wbuf)-1] = '\0'; //将容器中的换行变成'\0'//将该数据发送给子进程//3、向管道文件中写数据write(pipefd[1], wbuf, sizeof(wbuf));//参数1:要写入的文件描述符//参数2:要写入数据的起始地址//参数3:要写入数据的大小if(strcmp(wbuf, "quit") == 0){break;}}}wait(NULL); //阻塞回收子进程资源//关闭写端close(pipefd[1]);return 0;
}
3>共享内存
send:
int main()
{//1、获取key值key_t key;if((key = ftok("./", 'k')) == -1){perror("ftok error");return -1;}//2、创建共享内存int shmid;if((shmid = shmget(key, 4096, IPC_CREAT|0664)) == -1){perror("shmget error");return -1;}//3、映射内存地址char *addr = shmat(shmid, NULL, 0);if(addr == (void*)-1){perror("shmat error");return -1;}printf("addr = %p\n", addr); //输出共享内存的地址//向共享内存中写数据printf("请输入>>:");fgets(addr, SIZE, stdin); //直接从终端获取数据到共享内存中addr[strlen(addr) - 1] = 0;//4、取消映射if(shmdt(addr) == -1){perror("shmdt error");return -1;}//5、删除共享内存//shmctl(shmid, IPC_RMID, NULL);return 0;
}
recv:
int main()
{//1、获取key值key_t key;if((key = ftok("./", 'k')) == -1){perror("ftok error");return -1;}//2、创建共享内存int shmid;if((shmid = shmget(key, 4096, IPC_CREAT|0664)) == -1){perror("shmget error");return -1;}//3、映射内存地址char *addr = shmat(shmid, NULL, 0);if(addr == (void*)-1){perror("shmat error");return -1;}printf("addr = %p\n", addr); //输出共享内存的地址//读取共享内存中的内容printf("共享内存中的内容:%s\n", addr);//4、取消映射if(shmdt(addr) == -1){perror("shmdt error");return -1;}//5、删除共享内存//shmctl(shmid, IPC_RMID, NULL);return 0;
}