经过小小改动,把前面基础的例子做出一点修改。

并发服务器,服务器每accept一个请求就fork()一个新的子进程。

编译运行方法同前一篇。

  1. /*client_tcp.c*/
  2. #include <stdio.h>
  3. #include <unistd.h>
  4. #include <stdlib.h>
  5. #include <sys/types.h>
  6. #include <sys/socket.h>
  7. #include <sys/un.h>
  8.  
  9. #include <netinet/in.h>
  10.  
  11. #define MAXLINE 4096
  12. #define PORT 12345
  13.  
  14. void process(FILE *fp, int sockfd)
  15. {
  16. char send[MAXLINE], recv[MAXLINE];
  17. while (fgets(send, MAXLINE, fp) != NULL) {
  18. write(sockfd, send, strlen(send));
  19. int n = read(sockfd, recv, MAXLINE);
  20. recv[n] = ;
  21. fputs(recv, stdout);
  22. }
  23. }
  24.  
  25. int main(int argc, char *argv[])
  26. {
  27. int sockfd, n;
  28. ];
  29. struct sockaddr_in servaddr;
  30.  
  31. ) {
  32. fprintf(stderr, "usage: client_tcp <IP>\n");
  33. exit();
  34. }
  35.  
  36. )) < ) {
  37. fprintf(stderr, "socket error\n");
  38. exit();
  39. }
  40.  
  41. bzero(&servaddr, sizeof(servaddr));
  42. servaddr.sin_family = AF_INET;
  43. servaddr.sin_port = htons(PORT);
  44. ], &servaddr.sin_addr) <= ) {
  45. fprintf(stderr, ]);
  46. exit();
  47. }
  48.  
  49. if (connect(sockfd, (struct sockaddr *) &servaddr,
  50. ) {
  51. fprintf(stderr, "connect error\n");
  52. exit();
  53. }
  54.  
  55. process(stdin, sockfd);
  56.  
  57. exit();
  58. }
  1. /*server_tcp.c*/
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <stdio.h>
  5. #include <unistd.h>
  6. #include <sys/types.h>
  7. #include <sys/socket.h>
  8. #include <sys/un.h>
  9. #include <netinet/in.h>
  10.  
  11. #define MAXLINE 4096
  12. #define LISTENQ 1024
  13. #define PORT 12345
  14.  
  15. void process(int sockfd)
  16. {
  17. ssize_t n;
  18. ];
  19.  
  20. ) {
  21. write(sockfd, buff, n);
  22. }
  23. }
  24.  
  25. int main(int argc, char *argv[])
  26. {
  27. int listenfd, connfd;
  28. struct sockaddr_in servaddr, cliaddr;
  29. pid_t pid;
  30.  
  31. listenfd = socket(AF_INET, SOCK_STREAM, );
  32.  
  33. bzero(&servaddr, sizeof(servaddr));
  34. servaddr.sin_family = AF_INET;
  35. servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  36. servaddr.sin_port = htons(PORT);
  37.  
  38. bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr));
  39.  
  40. listen(listenfd, LISTENQ);
  41.  
  42. ) {
  43. int clilen = sizeof(cliaddr);
  44. connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &clilen);
  45.  
  46. ) {//child
  47. close(listenfd);
  48. process(connfd);
  49. exit();
  50. }
  51. close(connfd);
  52. }
  53.  
  54. exit();
  55. }

《UNIX网络编程》TCP客户端服务器:并发、消息回显的更多相关文章

  1. 《UNIX网络编程》UDP客户端服务器:消息回显

    udp写的程序相比tcp简单一些,在socket()与bind()之后,不需要connect(),accept()等步骤,直接简化为了sendto()与recvfrom(). 编译运行同前面的tcp. ...

  2. UNIX网络编程---TCP客户/服务器程序示例(五)

    一.概述 客户从标准输入读入一行文本,并写给服务器 服务器从网络输入读入这行文本,并回射给客户 客户从网络输入读入这行回射文本,并显示在标准输出上 二.TCP回射服务器程序:main函数 这里给了函数 ...

  3. [网络编程之客户端/服务器架构,互联网通信协议,TCP协议]

    [网络编程之客户端/服务器架构,互联网通信协议,TCP协议] 引子 网络编程 客户端/服务器架构 互联网通信协议 互联网的本质就是一系列的网络协议 OSI七层协议 tcp/ip五层模型 客户端/服务器 ...

  4. UNIX网络编程——select函数的并发限制和 poll 函数应用举例

    一.用select实现的并发服务器,能达到的并发数,受两方面限制 1.一个进程能打开的最大文件描述符限制.这可以通过调整内核参数.可以通过ulimit -n来调整或者使用setrlimit函数设置,  ...

  5. UNIX网络编程——TCP回射服务器/客户端程序

    下面通过最简单的客户端/服务器程序的实例来学习socket API. serv.c 程序的功能是从客户端读取字符然后直接回射回去: #include<stdio.h> #include&l ...

  6. UNIX网络编程——tcp流协议产生的粘包问题和解决方案

    我们在前面曾经说过,发送端可以是一K一K地发送数据,而接收端的应用程序可以两K两K地提走数据,当然也有可能一次提走3K或6K数据,或者一次只提走几个字节的数据,也就是说,应用程序所看到的数据是一个整体 ...

  7. unix网络编程——TCP套接字编程

    TCP客户端和服务端所需的基本套接字.服务器先启动,之后的某个时刻客户端启动并试图连接到服务器.之后客户端向服务器发送请求,服务器处理请求,并给客户端一个响应.该过程一直持续下去,直到客户端关闭,给服 ...

  8. Linux网络编程:客户端/服务器的简单实现

    一. Socket的基本知识 1. socket功能 Socket层次 Socket实质上提供了进程通信的端点,进程通信之前,双方必须首先各自创建一个端点,否则是没有办法建立联系并相互通信的. 每一个 ...

  9. 第5章-unix网络编程 TCP/服务端程序示例

    这一章主要是完成一个完整的tcp客户/服务器程序.通过一很简单的例子.弄清客户和服务器如何启动,如何终止,发生了某些错误会发生什么.这些事很重要的  客户端代码 #include "unp. ...

  10. python网络编程--TCP客户端的开发

    #导入socket模块 2 import socket 3 #参数说明 4 """ 5 socket类的介绍 6 创建客户端socket对象 7 socket.socke ...

随机推荐

  1. gcc常用命令集

    引用:http://developer.51cto.com/art/200609/32317_1.htm 对于GUN编译器来说,程序的编译要经历预处理.编译.汇编.连接四个阶段 假设源程序文件名为te ...

  2. 为什么JavaScript函数中的参数前面不能加var

    首先这里是JavaScript的语法规则. 其次在调用function()函数的时候参数时外部传入的.在传入之前就已经被声明了.没必要在函数参数里声明. 如果想要在函数里用新的参数 function( ...

  3. oracle存储参数(storage子句)含义及设置技巧

    可用于:表空间.回滚段.表.索引.分区.快照.快照日志 参数名称 缺省值 最小值 最大值 说明 INITIAL 5(数据块) 2(数据块) 操作系统限定 分配给Segment的第一个Extent的大小 ...

  4. 为什么我们需要性能测试,需要loadrunner

    什么是功能: 功能按我理解就是软件实现需求,提供服务,那么功能测试就是实现的需求是否与客户给定需求一致,也就是符合预期结果 什么是性能: 功能是实现需求,提供服务,那么性能就可以理解为服务的好坏.比如 ...

  5. nginx上传模块nginx_upload_module和nginx_uploadprogress_module模块进度显示,如何传递GET参数等。

    ownload:http://www.grid.net.ru/nginx/download/nginx_upload_module-2.2.0.tar.gzconfigure and make : . ...

  6. FPGA的LE数与门数的关系(转)

    一般而言FPGA等效门数的计算方法有两种 一是把FPGA基本单元(如LUT+FF,ESB/BRAM)和实现相同功能的标准门阵列比较,门阵列中包含的门数即为该FPGA基本单元的等效门数,然后乘以基本单元 ...

  7. 如何实现Linux下的U盘(USB Mass Storage)驱动

    如何实现Linux下的U盘(USB Mass Storage)驱动 版本:v0.7 How to Write Linux USB MSC (Mass Storage Class) Driver Cri ...

  8. C++的四种cast操作符的区别--类型转换

    Q:什么是C风格转换?什么是static_cast, dynamic_cast 以及 reinterpret_cast?区别是什么?为什么要注意? A:转换的含义是通过改变一个变量的类型为别的类型从而 ...

  9. 定时PING下IP地址,检测该服务器是否还活着。 smokeping

    http://oss.oetiker.ch/smokeping-demo/?displaymode=n;start=2014-10-16%2007:00;end=now;target=SIP

  10. [Leetcode][Python]48: Rotate Image

    # -*- coding: utf8 -*-'''__author__ = 'dabay.wang@gmail.com' 48: Rotate Imagehttps://leetcode.com/pr ...