unix网络编程各种TCP客户-服务器程序设计实例附环境搭建和编译方法(一)

一,到http://download.csdn.net/detail/ts173383201/4505201去下载源代码,然后解压;

二,cd到你解压后的文件夹下,就是有configure的那个目录下,执行命令./configure;

三,执行cd lib跳到lib目录下,执行make命令,会在上层目录(就是刚才有configure那个目录)生成libunp.a文件

四,复制这个静态库libunp.a到/usr/lib/和/usr/lib64/中;

五,接下来在目录中找到unp.h和config.h,在以后的代码中我们都要用到这两个头文件,将他们复制到和我们的源代码同一个路径下;

这样我们的环境就搭建好了,是不是很简单啊,但是以后编译的时候在gcc的最后加上-lunp导入静态库就可以了。下面我们就来看这些例子:

第一种:TCP迭代服务器程序:迭代服务器总是在完全处理了一个客户的请求后才响应下一个客户的请求。

客户端程序:daytimetcpcli.c

  1. #include    "unp.h"
  2. int
  3. main(int argc, char **argv)
  4. {
  5. int                 sockfd, n;
  6. char                recvline[MAXLINE + 1];
  7. struct sockaddr_in  servaddr;
  8. if (argc != 2)
  9. err_quit("usage: a.out <IPaddress>");
  10. if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  11. err_sys("socket error");
  12. bzero(&servaddr, sizeof(servaddr));
  13. servaddr.sin_family = AF_INET;
  14. servaddr.sin_port   = htons(13);    /* daytime server */
  15. if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0)
  16. err_quit("inet_pton error for %s", argv[1]);
  17. if (connect(sockfd, (SA *) &servaddr, sizeof(servaddr)) < 0)
  18. err_sys("connect error");
  19. while ( (n = read(sockfd, recvline, MAXLINE)) > 0) {
  20. recvline[n] = 0;    /* null terminate */
  21. if (fputs(recvline, stdout) == EOF)
  22. err_sys("fputs error");
  23. }
  24. if (n < 0)
  25. err_sys("read error");
  26. exit(0);
  27. }

服务器程序:daytimetcpsrv.c

  1. #include    "unp.h"
  2. #include    <time.h>
  3. int
  4. main(int argc, char **argv)
  5. {
  6. int                 listenfd, connfd;
  7. struct sockaddr_in  servaddr;
  8. char                buff[MAXLINE];
  9. time_t              ticks;
  10. listenfd = Socket(AF_INET, SOCK_STREAM, 0);
  11. bzero(&servaddr, sizeof(servaddr));
  12. servaddr.sin_family      = AF_INET;
  13. servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  14. servaddr.sin_port        = htons(13);   /* daytime server */
  15. Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));
  16. Listen(listenfd, LISTENQ);
  17. for ( ; ; ) {
  18. connfd = Accept(listenfd, (SA *) NULL, NULL);
  19. ticks = time(NULL);
  20. snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&ticks));
  21. Write(connfd, buff, strlen(buff));
  22. Close(connfd);
  23. }
  24. }

好,现在我们接着上面的步骤,将这两个源文件放到我们喜欢的目录下,再复制unp.h和config.h两个文件到同一个目录下;

执行下面的命令:

生成了server和client程序,运行server和client程序如下图,顺利成功:

第二种:TCP并发服务器程序,每个客户一个子进程

每个客户一个子进程:传统上,并发服务器调用fork派生一个子进程来处理每个客户。这使得服务器可在同一时间为多个客户提供服务。

回射服务器:

1, 客户从标准输入读一行文本,写到服务器上;

2, 服务器从网络输入读此行,并回射给客户;

3, 客户度此回射行并写到标准输出;

  1. #include    "unp.h"
  2. void
  3. sig_chld(int signo)
  4. {
  5. pid_t   pid;
  6. int     stat;
  7. while ( (pid = waitpid(-1, &stat, WNOHANG)) > 0)
  8. printf("child %d terminated\n", pid);
  9. return;
  10. }
  11. int
  12. main(int argc, char **argv)
  13. {
  14. int                 listenfd, connfd;
  15. pid_t               childpid;
  16. socklen_t           clilen;
  17. struct sockaddr_in  cliaddr, servaddr;
  18. void                sig_chld(int);
  19. listenfd = Socket(AF_INET, SOCK_STREAM, 0);
  20. bzero(&servaddr, sizeof(servaddr));
  21. servaddr.sin_family      = AF_INET;
  22. servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  23. servaddr.sin_port        = htons(SERV_PORT);
  24. Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));
  25. Listen(listenfd, LISTENQ);
  26. Signal(SIGCHLD, sig_chld);  /* must call waitpid() */
  27. for ( ; ; ) {
  28. clilen = sizeof(cliaddr);
  29. if ( (connfd = accept(listenfd, (SA *) &cliaddr, &clilen)) < 0) {
  30. if (errno == EINTR)
  31. continue;       /* back to for() */
  32. else
  33. err_sys("accept error");
  34. }
  35. if ( (childpid = Fork()) == 0) {    /* child process */
  36. Close(listenfd);    /* close listening socket */
  37. str_echo(connfd);   /* process the request */
  38. exit(0);
  39. }
  40. Close(connfd);          /* parent closes connected socket */
  41. }
  42. }
  1. str_echo.c:
  1. <p>#include "unp.h"</p><p>void
  2. str_echo(int sockfd)
  3. {
  4. ssize_t  n;
  5. char  buf[MAXLINE];</p><p>again:
  6. while ( (n = read(sockfd, buf, MAXLINE)) > 0)
  7. Writen(sockfd, buf, n);</p><p> if (n < 0 && errno == EINTR)
  8. goto again;
  9. else if (n < 0)
  10. err_sys("str_echo: read error");
  11. }</p>

注意:上面的Signal(SIGCHLD, sig_chld);是为了捕捉信号SIGCHLD并处理僵尸进程,有关僵尸进程的介绍请大家参看博文unix网络编程之基本套接口编程while ( (pid = waitpid(-1, &stat, WNOHANG)) > 0),这里我们不能用wait,由于wait会阻塞于没有子进程终止的情况所有不能用while循环每个终止信号。

客户端程序:

  1. #include    "unp.h"
  2. int
  3. main(int argc, char **argv)
  4. {
  5. int                 sockfd;
  6. struct sockaddr_in  servaddr;
  7. if (argc != 2)
  8. err_quit("usage: tcpcli <IPaddress>");
  9. sockfd = Socket(AF_INET, SOCK_STREAM, 0);
  10. bzero(&servaddr, sizeof(servaddr));
  11. servaddr.sin_family = AF_INET;
  12. servaddr.sin_port = htons(SERV_PORT);
  13. Inet_pton(AF_INET, argv[1], &servaddr.sin_addr);
  14. Connect(sockfd, (SA *) &servaddr, sizeof(servaddr));
  15. str_cli(stdin, sockfd);     /* do it all */
  16. exit(0);
  17. }

str_cli.c:

  1. #include    "unp.h"
  2. void
  3. str_cli(FILE *fp, int sockfd)
  4. {
  5. char    sendline[MAXLINE], recvline[MAXLINE];
  6. while (Fgets(sendline, MAXLINE, fp) != NULL) {
  7. Writen(sockfd, sendline, strlen(sendline));
  8. if (Readline(sockfd, recvline, MAXLINE) == 0)
  9. err_quit("str_cli: server terminated prematurely");
  10. Fputs(recvline, stdout);
  11. }
  12. }

最后像上面一样编译后运行即可,效果:

第三种:使用单进程和select/poll的TCP服务器程序

这种方法是用select来处理任意数目的客户的单进程程序,而不是像上面为每个客户派生一个子进程,在给出具体代码之前,让我们介绍一下背景知识,以及对用以跟踪客户的数据结构进行仔细的分析;

如果一个或多个I/O条件满足(例如,输入已准备好被读,或者描述字可以承接更多的输出)时,我们就被通知到。这个能力被称为I/O复用,是由函数select和poll支持的。

先介绍一下各种I/O模型:

阻塞I/O,非阻塞I/O,I/O复用,信号驱动I/O(SIGIO),异步I/O

对于一个套接口上的输入操作,第一步一般是等待数据到达网络,当分组到达时,它被拷贝到内核中的某个缓冲区,第二步是将数据从内核缓冲区拷贝到应用缓冲区。

select函数:

这个函数运行进程指示内核等待多个事件中的任一个发生,并仅在一个或多个事件发生或经过某指定的时间后才唤醒。

作为一个例子,我们可以调用函数select并通知内核仅在下列情况发生时才返回:

集合{1,4,5}中的任何描述字准备好读,或

集合{2,7}中任何描述字准备好些,或

集合{1,4}中的任何描述字有异常条件待处理,或

已经过了10.2秒

也就是说通知内核我们对哪些描述字感兴趣以及等待多长时间我们所关心的描述字不受限于套接口任何描述字都可用select来测试.

数据结构图示:

其中client[]用来揭露已连接描述字,而reset为读描述字集。

服务器程序:

  1. /* include fig01 */
  2. #include    "unp.h"
  3. int
  4. main(int argc, char **argv)
  5. {
  6. int                 i, maxi, maxfd, listenfd, connfd, sockfd;
  7. int                 nready, client[FD_SETSIZE];
  8. ssize_t             n;
  9. fd_set              rset, allset;
  10. char                buf[MAXLINE];
  11. socklen_t           clilen;
  12. struct sockaddr_in  cliaddr, servaddr;
  13. listenfd = Socket(AF_INET, SOCK_STREAM, 0);
  14. bzero(&servaddr, sizeof(servaddr));
  15. servaddr.sin_family      = AF_INET;
  16. servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  17. servaddr.sin_port        = htons(SERV_PORT);
  18. Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));
  19. Listen(listenfd, LISTENQ);
  20. maxfd = listenfd;           /* initialize */
  21. maxi = -1;                  /* index into client[] array */
  22. for (i = 0; i < FD_SETSIZE; i++)
  23. client[i] = -1;         /* -1 indicates available entry */
  24. FD_ZERO(&allset);
  25. FD_SET(listenfd, &allset);
  26. /* end fig01 */
  27. /* include fig02 */
  28. for ( ; ; ) {
  29. rset = allset;      /* structure assignment */
  30. nready = Select(maxfd+1, &rset, NULL, NULL, NULL);
  31. if (FD_ISSET(listenfd, &rset)) {    /* new client connection */
  32. clilen = sizeof(cliaddr);
  33. connfd = Accept(listenfd, (SA *) &cliaddr, &clilen);
  34. #ifdef  NOTDEF
  35. printf("new client: %s, port %d\n",
  36. Inet_ntop(AF_INET, &cliaddr.sin_addr, 4, NULL),
  37. ntohs(cliaddr.sin_port));
  38. #endif
  39. for (i = 0; i < FD_SETSIZE; i++)
  40. if (client[i] < 0) {
  41. client[i] = connfd; /* save descriptor */
  42. break;
  43. }
  44. if (i == FD_SETSIZE)
  45. err_quit("too many clients");
  46. FD_SET(connfd, &allset);    /* add new descriptor to set */
  47. if (connfd > maxfd)
  48. maxfd = connfd;         /* for select */
  49. if (i > maxi)
  50. maxi = i;               /* max index in client[] array */
  51. if (--nready <= 0)
  52. continue;               /* no more readable descriptors */
  53. }
  54. for (i = 0; i <= maxi; i++) {    /* check all clients for data */
  55. if ( (sockfd = client[i]) < 0)
  56. continue;
  57. if (FD_ISSET(sockfd, &rset)) {
  58. if ( (n = Read(sockfd, buf, MAXLINE)) == 0) {
  59. /*4connection closed by client */
  60. Close(sockfd);
  61. FD_CLR(sockfd, &allset);
  62. client[i] = -1;
  63. } else
  64. Writen(sockfd, buf, n);
  65. if (--nready <= 0)
  66. break;              /* no more readable descriptors */
  67. }
  68. }
  69. }
  70. }
  71. /* end fig02 */

使用poll的服务器程序:

  1. /* include fig01 */
  2. #include    "unp.h"
  3. #include    <limits.h>        /* for OPEN_MAX */
  4. int
  5. main(int argc, char **argv)
  6. {
  7. int                 i, maxi, listenfd, connfd, sockfd;
  8. int                 nready;
  9. ssize_t             n;
  10. char                buf[MAXLINE];
  11. socklen_t           clilen;
  12. struct pollfd       client[OPEN_MAX];
  13. struct sockaddr_in  cliaddr, servaddr;
  14. listenfd = Socket(AF_INET, SOCK_STREAM, 0);
  15. bzero(&servaddr, sizeof(servaddr));
  16. servaddr.sin_family      = AF_INET;
  17. servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  18. servaddr.sin_port        = htons(SERV_PORT);
  19. Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));
  20. Listen(listenfd, LISTENQ);
  21. client[0].fd = listenfd;
  22. client[0].events = POLLRDNORM;
  23. for (i = 1; i < OPEN_MAX; i++)
  24. client[i].fd = -1;      /* -1 indicates available entry */
  25. maxi = 0;                   /* max index into client[] array */
  26. /* end fig01 */
  27. /* include fig02 */
  28. for ( ; ; ) {
  29. nready = Poll(client, maxi+1, INFTIM);
  30. if (client[0].revents & POLLRDNORM) {   /* new client connection */
  31. clilen = sizeof(cliaddr);
  32. connfd = Accept(listenfd, (SA *) &cliaddr, &clilen);
  33. #ifdef  NOTDEF
  34. printf("new client: %s\n", Sock_ntop((SA *) &cliaddr, clilen));
  35. #endif
  36. for (i = 1; i < OPEN_MAX; i++)
  37. if (client[i].fd < 0) {
  38. client[i].fd = connfd;  /* save descriptor */
  39. break;
  40. }
  41. if (i == OPEN_MAX)
  42. err_quit("too many clients");
  43. client[i].events = POLLRDNORM;
  44. if (i > maxi)
  45. maxi = i;               /* max index in client[] array */
  46. if (--nready <= 0)
  47. continue;               /* no more readable descriptors */
  48. }
  49. for (i = 1; i <= maxi; i++) {    /* check all clients for data */
  50. if ( (sockfd = client[i].fd) < 0)
  51. continue;
  52. if (client[i].revents & (POLLRDNORM | POLLERR)) {
  53. if ( (n = read(sockfd, buf, MAXLINE)) < 0) {
  54. if (errno == ECONNRESET) {
  55. /*4connection reset by client */
  56. #ifdef  NOTDEF
  57. printf("client[%d] aborted connection\n", i);
  58. #endif
  59. Close(sockfd);
  60. client[i].fd = -1;
  61. } else
  62. err_sys("read error");
  63. } else if (n == 0) {
  64. /*4connection closed by client */
  65. #ifdef  NOTDEF
  66. printf("client[%d] closed connection\n", i);
  67. #endif
  68. Close(sockfd);
  69. client[i].fd = -1;
  70. } else
  71. Writen(sockfd, buf, n);
  72. if (--nready <= 0)
  73. break;              /* no more readable descriptors */
  74. }
  75. }
  76. }
  77. }
  78. /* end fig02 */

客服端程序:

  1. #include    "unp.h"
  2. void
  3. str_cli1(FILE *fp, int sockfd)
  4. {
  5. int         maxfdp1, stdineof;
  6. fd_set      rset;
  7. char        buf[MAXLINE];
  8. int     n;
  9. stdineof = 0;
  10. FD_ZERO(&rset);
  11. for ( ; ; ) {
  12. if (stdineof == 0)
  13. FD_SET(fileno(fp), &rset);
  14. FD_SET(sockfd, &rset);
  15. maxfdp1 = max(fileno(fp), sockfd) + 1;
  16. Select(maxfdp1, &rset, NULL, NULL, NULL);
  17. if (FD_ISSET(sockfd, &rset)) {  /* socket is readable */
  18. if ( (n = Read(sockfd, buf, MAXLINE)) == 0) {
  19. if (stdineof == 1)
  20. return;     /* normal termination */
  21. else
  22. err_quit("str_cli: server terminated prematurely");
  23. }
  24. Write(fileno(stdout), buf, n);
  25. }
  26. if (FD_ISSET(fileno(fp), &rset)) {  /* input is readable */
  27. if ( (n = Read(fileno(fp), buf, MAXLINE)) == 0) {
  28. stdineof = 1;
  29. Shutdown(sockfd, SHUT_WR);  /* send FIN */
  30. FD_CLR(fileno(fp), &rset);
  31. continue;
  32. }
  33. Writen(sockfd, buf, n);
  34. }
  35. }
  36. }
  37. int
  38. main(int argc, char **argv)
  39. {
  40. int                 sockfd;
  41. struct sockaddr_in  servaddr;
  42. if (argc != 2)
  43. err_quit("usage: tcpcli <IPaddress>");
  44. sockfd = Socket(AF_INET, SOCK_STREAM, 0);
  45. bzero(&servaddr, sizeof(servaddr));
  46. servaddr.sin_family = AF_INET;
  47. servaddr.sin_port = htons(SERV_PORT);
  48. Inet_pton(AF_INET, argv[1], &servaddr.sin_addr);
  49. Connect(sockfd, (SA *) &servaddr, sizeof(servaddr));
  50. str_cli1(stdin, sockfd);        /* do it all */
  51. exit(0);
  52. }

这里客服端程序用了shutdown关闭套接口来代替close;下面就来介绍一下两者的区别:

shutdown可以分别关闭读写或者同时关闭读写

如果关闭读,则接受缓冲区的未读出的所有数据都将丢失,以后不会再接受任何数据

如果关闭写,如果输出缓冲区内有数据,则所有的数据将发送出去后将发送一个FIN信号

而close则是关闭该socket,马上发送FIN信号,所有的未完成发送或者接受的数据都将被丢失

对于慢速网络,应该先进行shutdown,然后一定的时间延迟,再close该socket.

(在你已经发送成功后,而对方如果没有接受完毕,你此时如果关闭socket则对方将收到FIN信号,将不能在接收数据,因此容易出现数据丢失的问题,这是 我以前写聊天室时遇到的一个错误,客户端经常报一个与服务器的连接被重置,后来加了一个时间延迟就好了)

#include<sys/socket.h>

int shutdown(int sockfd,int how);

how 的方式有三种分别是

SHUT_RD(0):关闭sockfd上的读功能,此选项将不允许sockfd进行读操作。

SHUT_WR(1): 关闭sockfd的写功能,此选项将不允许sockfd进行写操作。

SHUT_RDWR(2):关闭sockfd的读写功能。

成 功则返回0,错误返回-1,错误码errno:EBADF表示sockfd不是一个有效描述符;ENOTCONN表示sockfd未连 接;ENOTSOCK表示sockfd是一个文件描述符而不是socket描述符。

close的定义如下:

#include<unistd.h>

int close(int fd);

关闭读写。

成功则返回0,错误返回-1,错误码errno:EBADF表示fd不是一个有效 描述符;EINTR表示close函数被信号中断;EIO表示一个IO错误。

下面摘用网上的一段话来说明二者的区别:

close----- 关闭本进程的socket id,但链接还是开着的,用这个socket id的其它进程还能用这个链接,能读或写这个socket id

shutdown-- 则破坏了socket 链接,读的时候可能侦探到EOF结束符,写的时候可能会收到一个SIGPIPE信号.

1>. 如果有多个进程共享一个套接字,close每被调用一次,计数减1,直到计数为0时,也就是所用进程都调用了close,套接字将被释放。

2>. 在多进程中如果一个进程中shutdown(sfd, SHUT_RDWR)后其它的进程将无法进行通信. 如果一个进程close(sfd)将不会影响到其它进程

拒绝服务性攻击:

当一个服务器正在处理多个客户时,服务器决不能阻塞于只与单个客户相关函数调用。如果这样的话,服务器悬挂并拒绝为所有其他客户提供服务,这称为拒绝服务攻击,当一个服务器正在处理多个客户时,服务器决不能阻塞于只与单个客户相关的函数调用。如果这样的话,服务器将悬挂并拒绝为所有其他客户提供服务,这称为拒绝服务型攻击。可能解决的办法有:使用非阻塞I/O模型;让每个客户由单独的控制线程提供服务;对I/O操作设置超时;

非阻塞I/O

缺省状态下,套接口是阻塞方式的。这意味着当一个套接口调用不能立即完成时,进程进入睡眠状态,等待操作的完成。我们将可能阻塞的套接口调用分成四种。

非阻塞connect:

在一个TCP套接口被设置为非阻塞后调用connect,connect会立即返回一个EINPROCESS错误,但TCP的三路握手继续进行。在这之后我们可以用select检查这个链接是否建立成功。

版权声明:本文为博主http://www.zuiniusn.com原创文章,未经博主允许不得转载。

时间: 2024-10-12 03:12:07

unix网络编程各种TCP客户-服务器程序设计实例附环境搭建和编译方法(一)的相关文章

unix网络编程各种TCP客户-服务器程序设计实例(二)

本节我们接着介绍另外的几种TCP客户-服务器程序: 第四种:TCP并发服务器,每个客户一个子线程 在我们前面的并发服务器程序例子中可以看出:父进程接受连接,派生子进程,子进程处理与客户的交互. 这种模式的问题: fork()是昂贵的.内存映像要从父进程拷贝到子进程,所有描述字要在子进程中复制等等. fork()子进程后,需要用进程间通信在父子进程之间传递信息. 一个进程中的所有线程共享相同的全局内存,这使得线程很容易共享信息,但是这种简易型也带来了同步问题.一个进程中的所有线程不仅共享全局变量,

unix网络编程各种TCP客户-服务器程序设计实例(三)

第五种  TCP预先派生子进程服务器程序: 对预先派生子进程服务器的最后一种改动就是由父进程调用accept,然后再将所接受的已连接描述字传递给子进程.父进程必须跟踪子进程的忙闲状态,以便给空闲子进程传递新的描述字.为每个子进程维护一个信息结构,用来管理各子进程. 在调用fork之前,先创建一个字节流管道(Unix域的字节流套接口),它是Unix域的字节流套接口.当子进程派生后,父进程关闭一个描述字(sockfd[1]),子进程关闭另一个描述字(sockfd[0]),此外,子进程将流管道的字节所

UNIX网络编程入门——TCP客户/服务器程序详解

前言 最近刚开始看APUE和UNP来学习socket套接字编程,因为网络这方面我还没接触过,要等到下学期才上计算机网络这门课,所以我就找了本教材啃了一两天,也算是入了个门. 至于APUE和UNP这两本书,书是好书,网上也说这书是给进入unix网络编程领域初学者的圣经,这个不可置否,但这个初学者,我认为指的是接受过完整计算机本科教育的研究生初学者,需要具有完整计算机系统,体系结构,网络基础知识.基础没打好就上来啃书反而会适得其反,不过对于我来说也没什么关系,因为基础课也都上得差不多了,而且如果书读

【UNIX网络编程】TCP客户/服务器程序示例

做一个简单的回射服务器: 客户从标准输入读入一行文本,写给服务器 -> 服务器从网络输入读入这行文本,并回射给客户 -> 客户从网络输入读入这行回射文本,并显示在标准输出上 以下是我的代码(部分.h文件是由unpv13e文件夹中的.c文件改名得到) #include "../unpv13e/unp.h" #include "../unpv13e/apueerror.h" #include "../unpv13e/wrapsock.h"

《UNIX网络编程》TCP客户端服务器:并发、消息回显

经过小小改动,把前面基础的例子做出一点修改. 并发服务器,服务器每accept一个请求就fork()一个新的子进程. 编译运行方法同前一篇. /*client_tcp.c*/ #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/un.h> #incl

Java网络编程(tcp在服务器上应用多线程)

package org.tcp; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.PrintStream; import java.net.Socket; public class EchoThread implements Runnable { private Socket client = null; public EchoThread(Socket client){ this.c

UNIX网络编程之旅-配置unp.h头文件环境

最近在学习Unix网络编程(UNP),书中steven在处理网络编程时只用了一个#include “unp.h”  相当有个性并且也很便捷 于是我把第三版的源代码编译实现了这个过程,算是一种个性化的开发环境的搭建吧,顺便把过程记录下来,以便自己以后查阅. 首先去网上找到源代码包unpv.13e.tar.gz 一找一大堆 解压缩到你的某个目录,unpv13e里面大致有这些目录 ├── aclocal.m4 ├── advio ├── bcast ├── config.guess ├── confi

《UNIX网络编程》入门客户端服务器例子

最近在看<UNIX网络编程>(简称unp)和<Linux程序设计>,对于unp中第一个获取服务器时间的例子,实践起来总是有点头痛的,因为作者将声明全部包含在了unp.h里,导致后面编写代码会对这个头文件造成依赖,而学习不到调用了相应功能之后,应该包含哪些确切的头文件. 再者,我下载了unp.h之后,头文件包含再次产生了其他的依赖缺失,因此便参考了<Linux程序设计>中socket一章的入门例子的头文件包含,并且编译中仍然找不到的包含或者是宏定义在unp.h中搜索并粘贴

第四章 基本TCP套接字编程 第五章 TCP客户/服务器程序实例

TCP客户与服务器进程之间发生的重大事件时间表 TCP服务器 socket() --- bind() --- listen() --- accept() --- read() --- write --- read() --- close TCP客户 socket() --- connect() --- write() --- read()  --- close() 套接字函数简介 int socket(int family, int type, int protocol); 指定要用的通信协议类