服务器端:
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: #include <signal.h>
27:
28: typedef struct sockaddr SA; //
29: #define N 128
30:
31: int main(int argc, char *argv[])
32: {
33: int listenfd, confd; //定义listend用于存放监听套接字的描述符,confd用于存放accept返回的已建立连接套接字的描述符。
34: struct sockaddr_in my_addr, peer_addr;//my_addr用于存放监听套接字要绑定的信息,peer_addr存放客户端套接字的信息
35: socklen_t peer_len = sizeof(my_addr); //peer_len最好定义时初始化,且必须初始化!
36: char buffer[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: signal(SIGCHLD, SIG_IGN); //防止产生僵尸进程,告诉OS,当子进程结束时,将子进程的task_struct也一并回收。
78:
79: while(1)
80: {
81: /*
82: 当没有客户端请求时,服务器在此阻塞。直到有客户端请求,然后返回一个新的套接字描述符confd,与
83: listenfd是相同类型的,但是confd可以用于与客户端收发数据,而listenfd不行,它只能监听。
84: 注意:accept返回的是一个新的已经与客户端建立连接的套接字confd,他有两个缓冲区,输入和输出,
85: 只有他才可以与客户端进行通信。他的类型与监听套接字一样。
86: */
87: if((confd = accept(listenfd, (SA *)&peer_addr, &peer_len)) < 0)
88: {
89: perror("accpt error!");
90: exit(-1);
91: }
92:
93: printf("client : [%s:%d] on line!\n",inet_ntoa(peer_addr.sin_addr), ntohs(peer_addr.sin_port));
94:
95: if(fork() == 0)
96: {
97: while(recv(confd, buffer, N,0) > 0) //将套接字confd的接收缓冲区的数据拷贝到buffer,当客户端关闭连接时,返回0。
98: {
99: printf("client : [%s:%d] > %s",inet_ntoa(peer_addr.sin_addr), ntohs(peer_addr.sin_port),buffer);
100: if(send(confd, buffer, N, 0) == -1) //将buffer中的数据拷贝到confd的发送缓冲区
101: {
102: perror("fail to send");
103: exit(-1);
104: }
105: }
106:
107: printf("client : [%s:%d] offline!\n",inet_ntoa(peer_addr.sin_addr), ntohs(peer_addr.sin_port));
108: close(confd);
109: exit(0);
110: }
111: close(confd);
112: }
113:
114: return 0;
115: }
客户端:
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: //buffer[strlen(buffer) - 1] = '\0';
70: if(send(sockfd, buffer, N, 0) == -1)
71: {
72: perror("fail to send");
73: exit(-1);
74: }
75: if(strncmp(buffer, "quit", 4) == 0)
76: {
77: break;
78: }
79: bzero(buffer, N);
80:
81: if(recv(sockfd, buffer, N, 0) == -1)
82: {
83: perror("fail to recv");
84: exit(-1);
85: }
86: printf("-------->%s> ",buffer);
87: }
88: close(sockfd);
89:
90: return 0;
91: }