一、技术简介

 (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通信的更多相关文章

  1. python socket和简单tcp通信实现

    python 服务端和客户端的简单交互 TCP服务端: 1 创建套接字,绑定套接字到本地IP与端口 s = socket.socket(socket.AF_INET,socket.SOCK_STREA ...

  2. [C++] socket - 1 [简单TCP通信C\S代码]

    服务端: #include<iostream> #include<winsock2.h> #include<stdio.h> #pragma comment(lib ...

  3. C# 简单Tcp通信demo

    Client 代码 private void btnSend_Click(object sender, EventArgs e) { TcpClient tcpClient = new TcpClie ...

  4. select实现简单TCP通信(ubuntu 18.04)

    一.服务器程序(server.c) #include <stdio.h> #include <unistd.h> #include <stdlib.h> #incl ...

  5. QT 简单 TCP 通信,发送数据到服务器

    1.首先 添加头文件 #include <QtNetwork/QTcpSocket> 并且 在 xxx.pro(xxx指工程的名称) 中QT += core gui下面,添加 下面两句句话 ...

  6. 【Java】同步阻塞式(BIO)TCP通信

    TCP BIO 背景 网络编程的基本模型是Clien/Server模型,也就是两个进程之间进行相互通信,其中服务端提供位置信息(绑定的IP地址和监听端口),客户端通过连接操作向服务端监听的地址发起连接 ...

  7. java 网络编程之TCP通信和简单的文件上传功能

    */ .hljs { display: block; overflow-x: auto; padding: 0.5em; color: #333; background: #f8f8f8; } .hl ...

  8. python 简单搭建非阻塞式单进程,select模式,epoll模式服务

    由于经常被抓取文章内容,在此附上博客文章网址:,偶尔会更新某些出错的数据或文字,建议到我博客地址 :  --> 点击这里 可以看我的上篇文章 <python 简单搭建阻塞式单进程,多进程, ...

  9. python 简单搭建阻塞式单进程,多进程,多线程服务

    由于经常被抓取文章内容,在此附上博客文章网址:,偶尔会更新某些出错的数据或文字,建议到我博客地址 :  --> 点击这里 我们可以通过这样子的方式去理解apache的工作原理 1 单进程TCP服 ...

随机推荐

  1. 解决zabbix3.4图表显示中文乱码问题

    问题描述: 在Zabbix界面设置中,已经调成中文语言,可能zabbix自身携带的字体还不够完美,出现如下乱码: 测试环境: zabbix 3.4(经测试,目前3.x版本都适用) 解决步骤: 1. 寻 ...

  2. 天梯赛 L2-001 紧急救援

    L2-001 紧急救援 (25 分) 作为一个城市的应急救援队伍的负责人,你有一张特殊的全国地图.在地图上显示有多个分散的城市和一些连接城市的快速道路.每个城市的救援队数量和每一条连接两个城市的快速道 ...

  3. JavaScript FormData的详细介绍及使用

    本文转自:https://blog.csdn.net/liupeifeng3514/article/details/78988001 FormData的详细介绍及使用请点击此处,那里对FormData ...

  4. 关于Nginx负载均衡的5种策略

    nginx的upstream目前支持的5种方式的分配 1.轮询(默认) 每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除. upstream backserver { ...

  5. 第三十六节,目标检测之yolo源码解析

    在一个月前,我就已经介绍了yolo目标检测的原理,后来也把tensorflow实现代码仔细看了一遍.但是由于这个暑假事情比较大,就一直搁浅了下来,趁今天有时间,就把源码解析一下.关于yolo目标检测的 ...

  6. AndroidStudio快速入门四:打造你的开发工具,settings必备

    http://blog.csdn.net/jf_1994/article/details/50085825 前言:这里是使用AS的基本设置,适合新入手的朋友阅读,将这里介绍的设置完基本使用无忧啦. 1 ...

  7. 多文件协作,extern、static、头文件

    多个cpp文件协同工作.使用外部函数.变量时,必须先声明再使用.声明外部函数(一般在main.cpp中),extern可省略(主函数中默认可访问外部函数)extern void RectArea(); ...

  8. java中异常的面试

    https://blog.csdn.net/qq_36523638/article/details/79363652 1) Java中的检查型异常和非检查型异常有什么区别? 这又是一个非常流行的Jav ...

  9. Linux设备树(一 概述)

    一 概述 设备树(Device tree)是一套用来描述硬件属相的规则.ARM Linux采用设备树机制源于2011年3月份Linux创始人Linus Torvalds发的一封邮件,在这封邮件中他提倡 ...

  10. qml: 以鼠标为中心进行放缩;

    import QtQuick 2.9 import QtQuick.Window 2.2 import QtQuick.Controls 2.2 Window { visible: true widt ...