阻塞式I/O实现简单TCP通信
一、技术简介
(1)服务端打开两个端口9999和6666监听外来连接;
(2)服务端的子进程通过端口9999监听外来消息,通过端口6666发送消息;
(3)客户端的子进程处理外来消息,父进程发送消息
二、服务器程序
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/un.h> #define SERV_PORT1 9999
#define SERV_PORT2 6666
#define MAXLINE 4096 #define SA struct sockaddr void send_msg(int);
void listen_msg(int, const struct sockaddr*);
char *sock_ntop(const struct sockaddr*, socklen_t); int main(int argc, char *argv[]) {
int listenfd1, connfd1;
int listenfd2, connfd2;
pid_t childpid;
socklen_t clilen1, clilen2;
struct sockaddr_in servaddr1, servaddr2;
struct sockaddr_in cliaddr1, cliaddr2; listenfd1 = socket(AF_INET, SOCK_STREAM, );
listenfd2 = socket(AF_INET, SOCK_STREAM, ); bzero(&servaddr1, sizeof(servaddr1));
servaddr1.sin_family = AF_INET;
servaddr1.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr1.sin_port = htons(SERV_PORT1); bzero(&servaddr2, sizeof(servaddr2));
servaddr2.sin_family = AF_INET;
servaddr2.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr2.sin_port = htons(SERV_PORT2); bind(listenfd1, (SA *)&servaddr1, sizeof(servaddr1));
bind(listenfd2, (SA *)&servaddr2, sizeof(servaddr2)); listen(listenfd1, );
listen(listenfd2, ); clilen1 = sizeof(cliaddr1);
clilen2 = sizeof(cliaddr2);
connfd1 = accept(listenfd1, (SA *)&cliaddr1, &clilen1);
connfd2 = accept(listenfd2, (SA *)&cliaddr2, &clilen2); if (connfd1 && connfd2) {
if ( (childpid = fork()) == ) {
close(listenfd2);
close(connfd2);
close(listenfd1);
listen_msg(connfd1, (SA *)&cliaddr1);
close(connfd1);
exit();
}
close(listenfd1);
close(connfd1);
close(listenfd2);
send_msg(connfd2);
close(connfd2);
}
exit();
} void listen_msg(int sockfd, const struct sockaddr *addr) {
ssize_t n;
char buf[MAXLINE]; while ( (n = read(sockfd, buf, MAXLINE)) > ) {
printf("[%s]: ", sock_ntop(addr, sizeof(addr)));
fputs(buf, stdout);
bzero(buf, sizeof(buf));
}
} void send_msg(int sockfd) {
char buf[MAXLINE]; while (fgets(buf, MAXLINE, stdin) != NULL) {
write(sockfd, buf, sizeof(buf));
}
} char *sock_ntop(const struct sockaddr *sa, socklen_t salen) { char portstr[];
static char str[]; switch (sa->sa_family) {
case AF_INET: {
struct sockaddr_in *sin = (struct sockaddr_in *) sa; if (inet_ntop(AF_INET, &sin->sin_addr, str,
sizeof(str)) == NULL) {
return(NULL);
}
if (ntohs(sin->sin_port) != ) {
snprintf(portstr, sizeof(portstr), ":%d",
ntohs(sin->sin_port));
strcat(str, portstr);
}
return(str);
}
case AF_INET6: {
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa; str[] = '[';
if (inet_ntop(AF_INET6, &sin6->sin6_addr, str + ,
sizeof(str) - ) == NULL) {
return(NULL);
}
if (ntohs(sin6->sin6_port) != ) {
snprintf(portstr, sizeof(portstr), "]:%d",
ntohs(sin6->sin6_port));
strcat(str, portstr);
return(str);
}
return (str + );
}
case AF_UNIX: {
struct sockaddr_un *unp = (struct sockaddr_un *) sa; if (unp->sun_path[] == ) {
strcpy(str, "(no pathname bound)");
} else {
snprintf(str, sizeof(str), "%s", unp->sun_path);
}
return(str);
}
default: {
snprintf(str, sizeof(str), "sock_ntop: unknown AF_xxx: %d, len %d",
sa->sa_family, salen);
return(str);
}
}
return (NULL);
}
三、客户端程序
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/un.h> #define SA struct sockaddr
#define SERV_PORT1 9999
#define SERV_PORT2 6666
#define MAXLINE 4096 void send_msg(int);
void listen_msg(int, const struct sockaddr*);
char *sock_ntop(const struct sockaddr*, socklen_t); int main(int argc, char *argv[]) {
pid_t childpid;
int sockfd1,sockfd2;
int connstatus1, connstatus2;
struct sockaddr_in servaddr1, servaddr2; if (argc != ) {
printf("usage: %s <IPaddress>\n", argv[]);
exit();
} sockfd1 = socket(AF_INET, SOCK_STREAM, );
sockfd2 = socket(AF_INET, SOCK_STREAM, ); bzero(&servaddr1, sizeof(servaddr1));
servaddr1.sin_family = AF_INET;
servaddr1.sin_port = htons(SERV_PORT1);
inet_pton(AF_INET, argv[], &servaddr1.sin_addr); bzero(&servaddr2, sizeof(servaddr2));
servaddr2.sin_family = AF_INET;
servaddr2.sin_port = htons(SERV_PORT2);
inet_pton(AF_INET, argv[], &servaddr2.sin_addr); connstatus1 = connect(sockfd1, (SA *)&servaddr1, sizeof(servaddr1));
connstatus2 = connect(sockfd2, (SA *)&servaddr2, sizeof(servaddr2)); if (connstatus1 == && connstatus2 == ) {
if ( (childpid = fork()) == ) {
close(sockfd1);
listen_msg(sockfd2, (SA *)&servaddr2);
close(sockfd2);
exit();
}
close(sockfd2);
send_msg(sockfd1);
close(sockfd1);
} else {
printf("connect failed!\n");
}
exit();
} void listen_msg(int sockfd, const struct sockaddr *addr) {
ssize_t n;
char buf[MAXLINE]; while ( (n = read(sockfd, buf, MAXLINE)) > ) {
printf("[%s]: ", sock_ntop(addr, sizeof(addr)));
fputs(buf, stdout);
bzero(buf, sizeof(buf));
}
} void send_msg(int sockfd) {
char buf[MAXLINE]; while (fgets(buf, MAXLINE, stdin) != NULL) {
write(sockfd, buf, sizeof(buf));
}
} char *sock_ntop(const struct sockaddr *sa, socklen_t salen) { char portstr[];
static char str[]; switch (sa->sa_family) {
case AF_INET: {
struct sockaddr_in *sin = (struct sockaddr_in *) sa; if (inet_ntop(AF_INET, &sin->sin_addr, str,
sizeof(str)) == NULL) {
return(NULL);
}
if (ntohs(sin->sin_port) != ) {
snprintf(portstr, sizeof(portstr), ":%d",
ntohs(sin->sin_port));
strcat(str, portstr);
}
return(str);
}
case AF_INET6: {
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa; str[] = '[';
if (inet_ntop(AF_INET6, &sin6->sin6_addr, str + ,
sizeof(str) - ) == NULL) {
return(NULL);
}
if (ntohs(sin6->sin6_port) != ) {
snprintf(portstr, sizeof(portstr), "]:%d",
ntohs(sin6->sin6_port));
strcat(str, portstr);
return(str);
}
return (str + );
}
case AF_UNIX: {
struct sockaddr_un *unp = (struct sockaddr_un *) sa; if (unp->sun_path[] == ) {
strcpy(str, "(no pathname bound)");
} else {
snprintf(str, sizeof(str), "%s", unp->sun_path);
}
return(str);
}
default: {
snprintf(str, sizeof(str), "sock_ntop: unknown AF_xxx: %d, len %d",
sa->sa_family, salen);
return(str);
}
}
return (NULL);
}
阻塞式I/O实现简单TCP通信的更多相关文章
- python socket和简单tcp通信实现
python 服务端和客户端的简单交互 TCP服务端: 1 创建套接字,绑定套接字到本地IP与端口 s = socket.socket(socket.AF_INET,socket.SOCK_STREA ...
- [C++] socket - 1 [简单TCP通信C\S代码]
服务端: #include<iostream> #include<winsock2.h> #include<stdio.h> #pragma comment(lib ...
- C# 简单Tcp通信demo
Client 代码 private void btnSend_Click(object sender, EventArgs e) { TcpClient tcpClient = new TcpClie ...
- select实现简单TCP通信(ubuntu 18.04)
一.服务器程序(server.c) #include <stdio.h> #include <unistd.h> #include <stdlib.h> #incl ...
- QT 简单 TCP 通信,发送数据到服务器
1.首先 添加头文件 #include <QtNetwork/QTcpSocket> 并且 在 xxx.pro(xxx指工程的名称) 中QT += core gui下面,添加 下面两句句话 ...
- 【Java】同步阻塞式(BIO)TCP通信
TCP BIO 背景 网络编程的基本模型是Clien/Server模型,也就是两个进程之间进行相互通信,其中服务端提供位置信息(绑定的IP地址和监听端口),客户端通过连接操作向服务端监听的地址发起连接 ...
- java 网络编程之TCP通信和简单的文件上传功能
*/ .hljs { display: block; overflow-x: auto; padding: 0.5em; color: #333; background: #f8f8f8; } .hl ...
- python 简单搭建非阻塞式单进程,select模式,epoll模式服务
由于经常被抓取文章内容,在此附上博客文章网址:,偶尔会更新某些出错的数据或文字,建议到我博客地址 : --> 点击这里 可以看我的上篇文章 <python 简单搭建阻塞式单进程,多进程, ...
- python 简单搭建阻塞式单进程,多进程,多线程服务
由于经常被抓取文章内容,在此附上博客文章网址:,偶尔会更新某些出错的数据或文字,建议到我博客地址 : --> 点击这里 我们可以通过这样子的方式去理解apache的工作原理 1 单进程TCP服 ...
随机推荐
- JS中的continue,break,return的区别
关于continue.break.return的用法区别早在大一C语言学习中研究过,这里单独拿出来,总结一下. 还是来点实在的吧,上代码 <!DOCTYPE html PUBLIC " ...
- Oracle数据库中遇到的坑
最近在帮别人忙写程序,用的是Oracle数据库,写一篇文章来说说在Oracle中遇到的一些坑: 1. PL/SQL develop的坑: 由于在这里工作环境是内网完全,无奈只能使用PL/SQL 工具, ...
- ie烦人的bug篇
好多公司都不支持ie6了,基本都是ie8+,就连jq新版本也宣布放弃低版本ie,就不用说那些框架了,不过想用兼容ie的angularjs可以用我司徒大神写的avalon,个人感觉avalon也是比较好 ...
- Java io概述
内容来源:http://ifeve.com/java-io/ Java IO 概述 输入流可以理解为向内存输入,输出流可以理解为从内存输出 Java的IO包主要关注的是从原始数据源的读取以及输出原始数 ...
- CSS解决文字超出显示省略号问题
超出一行 white-space: nowrap; overflow: hidden; text-overflow: ellipsis; 超出多行 overflow: hidden; text-ove ...
- C# http请求带请求头部分
直接上代码 前台调用: <script type="text/javascript"> function zLoginCheck() { var Account = ' ...
- Django(四)框架之第三篇模板语法
https://www.cnblogs.com/yuanchenqi/articles/6083427.htm https://www.cnblogs.com/haiyan123/p/7725568. ...
- ElasticSearch6.5.0【Java客户端之TransportClient】
说明 TransportClient:网上流传最多的客户端,目前最新版本 Java REST Client:官方推荐的客户端, 官方:我们要在Elasticsearch 7.0的版本中不赞成使用Tra ...
- 关键字(3):order by/group by/having/where/sum/count(*)...查询结果筛选关键字
ORDER BY <属性表> 只要在WHERE子句的选择条件后面加上如下子句:ORDER BY <属性表> 就可以实现输出的排序,默认的顺序为升序(ASC).可以在属性的后面加 ...
- Intellij Idea识别Java Web项目
使用maven生成一个Java项目,手动添加相应的web目录WEB_INF,web.xml等,此时idea没有自动识别为web项目,此时编辑web.xml文件会出现一些不该出现的错误,需要做的就是让i ...