下面程序实现的功能是:客户端将从键盘输入的内容发送给服务器,然后服务器在将受到的数据原封不动的发给客户端。

 

先看看服务器端的程序:



1:  /*
2:   * =====================================================================================
3:   *
4:   *       Filename:  server.c
5:   *
6:   *    Description:  tcp
7:   *
8:   *        Version:  1.0
9:   *        Created:  03/11/2013 02:34:43 PM
10:   *       Revision:  none
11:   *       Compiler:  gcc
12:   *
13:   *         Author:  YOUR NAME (),
14:   *        Company:
15:   *
16:   * =====================================================================================
17:   */
18:
19:  #include <stdio.h>
20:  #include <sys/socket.h>
21:  #include <netinet/in.h>
22:  #include <arpa/inet.h>
23:  #include <string.h>
24:  #include <stdlib.h>
25:  #include <unistd.h>
26:
27:  typedef struct sockaddr SA;  //
28:  #define N 128
29:
30:  int main(int argc, char *argv[])
31:  {
32:      int listenfd, confd;  //定义listend用于存放监听套接字的描述符,confd用于存放accept返回的已建立连接套接字的描述符。
33:      struct sockaddr_in my_addr, peer_addr;//my_addr用于存放监听套接字要绑定的信息,peer_addr存放客户端套接字的信息
34:      socklen_t peer_len = sizeof(my_addr);  //peer_len最好定义时初始化,且必须初始化!
35:      char buffer[N]; //
36:      int n;
37:
38:      if(argc < 3)  //参数检查
39:      {
40:          printf("input error! %s <ip> <port>\n",argv[0]);
41:          exit(-1);
42:      }
43:
44:      if((listenfd = socket(PF_INET, SOCK_STREAM, 0)) < 0)  //创建套接字,用于TCP连接
45:      {
46:          perror("socket error!");
47:          exit(-1);
48:      }
49:
50:     bzero(&my_addr, sizeof(my_addr));  //先将my_addr清空
51:
52:     //初始化监听套接字的绑定信息
53:     my_addr.sin_family = PF_INET;     //网络协议
54:
55:     /*
56:        ./client 192.168.1.173 8888
57:        argv[2]中是字符串“8888”的首地址,atoi将字符串“8888”,转化成数字8888,
58:        因为端口号是需要发送的,所以需要转换成网络字节序,通过htons实现
59:     */
60:     my_addr.sin_port = htons(atoi(argv[2]));
61:
62:     my_addr.sin_addr.s_addr = inet_addr(argv[1]);//将字符串"192.168.1.173"转成32位的无符号整型
63:
64:     if(bind(listenfd, (SA *)&my_addr, sizeof(my_addr)) < 0)  //将监听套接字进行绑定
65:     {
66:         perror("error bind");
67:         exit(-1);
68:     }
69:
70:     if(listen(listenfd, 5) < 0)  //将监听套接字设置为监听模式,等待请求队列长度为5
71:     {
72:
73:         perror("listen error!");
74:         exit(-1);
75:     }
76:
77:     while(1)
78:     {
79:     /*
80:           当没有客户端请求时,服务器在此阻塞。直到有客户端请求,然后返回一个新的套接字描述符confd,与
81:           listenfd是相同类型的,但是confd可以用于与客户端收发数据,而listenfd不行,它只能监听。
82:           注意:accept返回的是一个新的已经与客户端建立连接的套接字confd,他有两个缓冲区,输入和输出,
83:           只有他才可以与客户端进行通信。他的类型与监听套接字一样。
84:     */
85:         if((confd = accept(listenfd, (SA *)&peer_addr, &peer_len)) < 0)
86:         {
87:             perror("accpt error!");
88:             exit(-1);
89:         }
90:
91:         printf("client : [%s:%d]\n",inet_ntoa(peer_addr.sin_addr), ntohs(peer_addr.sin_port));
92:
93:         while(recv(confd, buffer, N,0) > 0)  //将套接字confd的接收缓冲区的数据拷贝到buffer,当客户端关闭连接时,返回0。
94:         {
95:             printf("I have get > %s",buffer);
96:             if(send(confd, buffer, N, 0) == -1)   //将buffer中的数据拷贝到confd的发送缓冲区
97:             {
98:                 perror("fail to send");
99:                 exit(-1);
100:             }
101:         }
102:
103:         printf("client : [%s:%d] have closed!\n",inet_ntoa(peer_addr.sin_addr), ntohs(peer_addr.sin_port));
104:         close(confd);
105:     }
106:
107:      return 0;
108:  }


 

客户端:

 



1:  /*
2:   * =====================================================================================
3:   *
4:   *       Filename:  server.c
5:   *
6:   *    Description:  tcp
7:   *
8:   *        Version:  1.0
9:   *        Created:  03/11/2013 02:34:43 PM
10:   *       Revision:  none
11:   *       Compiler:  gcc
12:   *
13:   *         Author:  YOUR NAME (),
14:   *        Company:
15:   *
16:   * =====================================================================================
17:   */
18:
19:  #include <stdio.h>
20:  #include <sys/socket.h>
21:  #include <sys/types.h>
22:  #include <netinet/in.h>
23:  #include <arpa/inet.h>
24:  #include <string.h>
25:  #include <stdlib.h>
26:  #include <unistd.h>
27:
28:
29:  #define N 128
30:
31:  typedef struct sockaddr SA;
32:
33:  int main(int argc, char *argv[])
34:  {
35:      int sockfd;  //客户端套接字,客户端只需一个,且不需要绑定
36:      struct sockaddr_in server_addr;  //服务器的ip端口信息
37:      char buffer[N];
38:
39:      if(argc < 3)
40:      {
41:          printf("usage! %s <ip> <port>\n",argv[0]);
42:          exit(-1);
43:      }
44:
45:      if((sockfd = socket(PF_INET, SOCK_STREAM, 0)) < 0)   //创建客户端套接字
46:      {
47:          perror("socket error!");
48:          exit(-1);
49:      }
50:
51:     bzero(&server_addr, sizeof(server_addr));
52:
53:     /*
54:     初始化要连接的服务器信息
55:     */
56:     server_addr.sin_family = PF_INET;
57:     server_addr.sin_port = htons(atoi(argv[2]));
58:     server_addr.sin_addr.s_addr = inet_addr(argv[1]);
59:
60:     if(connect(sockfd, (SA *)&server_addr, sizeof(server_addr)) < 0)  //连接服务器
61:     {
62:         perror("fail to connect");
63:         exit(-1);
64:     }
65:
66:     printf("> ");
67:     while(fgets(buffer, N, stdin) != 0)
68:     {
69:         if(send(sockfd, buffer, N, 0) == -1)
70:         {
71:             perror("fail to send");
72:             exit(-1);
73:         }
74:          if(strncmp(buffer, "quit", 4) == 0)
75:          {
76:              break;
77:          }
78:         bzero(buffer, N);
79:
80:         if(recv(sockfd, buffer, N, 0) == -1)
81:         {
82:             perror("fail to recv");
83:             exit(-1);
84:         }
85:         printf("-------->%s\n> ",buffer);
86:     }
87:     close(sockfd);
88:
89:      return 0;
90:  }