一、技术简介

 (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. PHP-FPM监控shell

    !/bin/bash #监控的网页地址url="http://dev2.jwsmed.com" #fastcgi启动/重启/停止脚本路径PROG=/data/fistsoft/ph ...

  2. 一个ArrayList在循环过程中删除,会不会出问题,为什么?

    ArrayList中的remove方法(注意ArrayList中的remove有两个同名方法,只是入参不同,这里看的是入参为Object的remove方法)是怎么实现的: public boolean ...

  3. MySQL 到底能不能放到 Docker 里跑?

    https://weibo.com/ttarticle/p/show?id=2309404296528549285581 前言 前几月经常看到有 MySQL 到底能不能放到 Docker 里跑的各种讨 ...

  4. 组件之间的数据传递--Vuex

    安装Vuex: npm install Vuex -S 在main.js中引入 import Vue from 'vue' import App from './App' import Vuex fr ...

  5. 洛谷P1463 反素数

    经典题了,很难想到这TM是搜索...... 题意:求[1, n]中约数最多的数中最小的. 解:我们有约数个数定理. 所以考虑通过枚举每个质因数个数来直接计算出约数个数. 然后就可以搜索了. 注意:若p ...

  6. LOJ#2302 整数

    解:发现这苟东西是个3千万位的二进制数......毒瘤吧. 拆位考虑,如果一个地方本来是1然后+1,就会把它和它前面连续的一段1变成0,并把第一个0变成1. 如果本来是0然后-1了,就会把它和它前面连 ...

  7. Python之迭代器,生成器

    迭代器 1.什么是可迭代对象 字符串.列表.元组.字典.集合都可以被for循环,说明他们都是可迭代的. from collections import Iterable l = [1,2,3,4] t ...

  8. 原生JS实现jquery的ready

    function ready(fn){ if(document.addEventListener){ //标准浏览器 document.addEventListener('DOMContentLoad ...

  9. java 学习:在java中启动其他应用,由jenkins想到的

    在jenkins的实践中遇到了一个问题: 我的项目依赖其他第三方应用的地方比较多,而且会占用多个端口,如何处理端口和启动/关闭第三方应用成了难题. 初级解决方案:在服务端上面写一堆bat文件,,,,_ ...

  10. 记cccc天梯赛第三届决赛

        首先我很想知道,为什么我没有参加初赛,就可以去决赛,这个究竟有没有初赛,这真是未解之谜.     其次,会长说得不错,菜是原罪.不知道这次的表现能不能把我送去湘潭挑战赛....     我身边 ...