socket编程(三)
来源:互联网 发布:线切割3b编程实例宝剑 编辑:程序博客网 时间:2024/06/10 13:10
REUSEADDR
- 服务器端尽可能使用
REUSEADDR
- 在绑定之前尽可能调用
setsocketopt
来设置REUSEADDR
套接字选项 - 使用
REUSEADDR
选项可以使得不必等待TIME_WAIT
状态消失就可以重启服务器
int on = 1;//选项开启标志 //设置地址重复利用 if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0){ perror("setsockopt error."); exit(1); }
处理多客户端连接
- 一个连接由一个子进程来处理并发
pid_t pid; while(1){ if((conn = accept(listenfd, (struct sockaddr*)&peeraddr, &peerlen)) < 0){ perror("accept() error."); exit(1); } printf("ip = %s, port = %d\n", inet_ntoa(peeraddr.sin_addr), ntohs(peeraddr.sin_port)); //一旦获得一个连接就创建一个进程出来 pid = fork(); if(pid == -1){ perror("fork error"); exit(1); } //子进程 if(pid == 0){ close(listenfd); char recvbuf[1024]; while(1){ memset(recvbuf, 0, sizeof(recvbuf)); int ret = read(conn, recvbuf, sizeof(recvbuf)); //捕捉客户端关闭 if(ret == 0){ printf("client close\n"); break; } else if(ret == -1) { perror("read erro"); exit(1); } fputs(recvbuf, stdout); write(conn, recvbuf, ret); } //销毁客户端开辟的进程 exit(EXIT_SUCCESS); } else { close(conn); } }
聊天程序实现
- 用多进程方式实现点对点聊天
- 一个进程用来获得输入,一个进程用来获得对方发来的消息
客户端
//p2pcli.c#include <stdio.h>#include <string.h>#include <stdlib.h>#include <sys/socket.h>#include <arpa/inet.h>#include <netinet/in.h>#include <sys/types.h>#include <unistd.h>#include <errno.h>#include <signal.h>void handler(int sig){ exit(EXIT_SUCCESS);}int main(){ int sock; //创建一个套接字 if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0){ perror("Creat socket failed."); exit(1); } /*int socket(int domain, int type, int protocol);*/ struct sockaddr_in servaddr; memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(9000); servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); /*servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");*/ /*inet_aton("127.0.0.1", &servaddr.sin_addr);*/ if(connect(sock, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0){ perror("connect() error"); exit(1); } // pid_t pid; pid = fork(); if(pid == -1){ perror("fork() error"); } if(pid == 0){ //子进程接收对方发送的数据 char recvbuf[1024] = {0}; while(1){ memset(recvbuf, 0, sizeof(recvbuf)); int ret = read(sock, recvbuf, sizeof(recvbuf)); if(ret == -1){ perror("read() error"); exit(1); } else if(ret == 0){ printf("peer close\n"); break; } fputs(recvbuf, stdout); } close(sock); kill(getppid(), SIGUSR1);//通知父进程退出 exit(EXIT_SUCCESS); } else { //主进程发送数据 signal(SIGUSR1, handler); char sendbuf[1024] = {0}; while(fgets(sendbuf, sizeof(sendbuf), stdin) != NULL){ write(sock, sendbuf, strlen(sendbuf)); memset(sendbuf, 0, sizeof(sendbuf)); } close(sock); exit(EXIT_SUCCESS); } return 0;}
服务器端
//p2pserv.c#include <stdio.h>#include <string.h>#include <stdlib.h>#include <sys/socket.h>#include <arpa/inet.h>#include <netinet/in.h>#include <sys/types.h>#include <unistd.h>#include <errno.h>#include <signal.h>void handler(int sig){ exit(EXIT_SUCCESS);}int main(){ int listenfd; //创建一个套接字 if((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){ perror("Create socket failed."); exit(1); } /*int socket(int domain, int type, int protocol);*/ struct sockaddr_in servaddr; memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(9000); servaddr.sin_addr.s_addr = htonl(INADDR_ANY); /*servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");*/ /*inet_aton("127.0.0.1", &servaddr.sin_addr);*/ int on = 1;//选项开启标志 //设置地址重复利用 if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0){ perror("setsockopt error."); exit(1); } if(bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0){ perror("bind error."); exit(1); } //绑定 if(listen(listenfd, SOMAXCONN) < 0){ perror("listen() error."); exit(1); } //监听 struct sockaddr_in peeraddr; socklen_t peerlen = sizeof(peeraddr); int conn; if((conn = accept(listenfd, (struct sockaddr*)&peeraddr, &peerlen)) < 0){ perror("accept() error"); exit(1); } printf("ip = %s, port = %d\n", inet_ntoa(peeraddr.sin_addr), ntohs(peeraddr.sin_port)); // pid_t pid; pid = fork(); if(pid == -1){ perror("fork() error"); exit(1); } if(pid == 0){ //发送数据的子进程 signal(SIGUSR1, handler); char sendbuf[1024] = {0}; while(fgets(sendbuf, sizeof(sendbuf), stdin) != NULL){ write(conn, sendbuf, strlen(sendbuf)); memset(sendbuf, 0, sizeof(sendbuf)); } exit(EXIT_SUCCESS); } else { //父进程用于获取对方发送的数据 char recvbuf[1024]; while (1){ memset(recvbuf, 0, sizeof(recvbuf)); int ret = read(conn, recvbuf, sizeof(recvbuf)); if(ret == -1){ perror("read error"); exit(1); } else if(ret == 0){ printf("peer close\n"); break; } fputs (recvbuf, stdout); } kill(pid, SIGUSR1);//通知子进程退出 exit(EXIT_SUCCESS); } return 0;}
实验结果
阅读全文
0 0
- socket编程(三)
- socket编程(三)
- socket编程(三)
- Java Socket编程(三)
- Java Socket编程(三)
- Java socket编程(三)
- Java(三) Socket编程
- socket 编程基础(三)
- linux socket 编程(三)
- Socket 基础编程(三)
- socket编程入门(三)
- Java Socket编程(三)服务器Sockets
- Java Socket编程(三) 服务器Sockets
- python Socket编程(三)----SMTP POP3
- java网络编程(三)socket
- Android中的socket编程(三)
- Socket网络编程笔记(三)
- Linux下Socket编程学习(三)
- 南阳理工学院ACM完全覆盖
- golang实现python xrange方法
- 用GParted工具修改Ubuntu系统中/home分区大小
- uml 类图中+
- java spring mvc 整合hibernate+自定义sql处理操作+数据库连接池
- socket编程(三)
- 手动控制云信的多段登录
- SpringMVC相关笔记
- Learn X in Y minutes
- VLC的视频编音频等码格式的缩写
- 二叉树
- spring4天计划(3day)
- 计算字符个数
- Gulp 常用插件