socket编程

Posted on 2012-05-22 17:36  逝水如年  阅读(221)  评论(0)    收藏  举报
 1 /*
 2  * 说明:服务器调用socket()、bind()、listen()完成初始化后,调用accept()阻塞等待,处于监听端口状态,
 3  * 客户端调用socket()初始化后,调用connect() 发出SYN段并阻塞等待服务器应答,服务器应答一个SYN-ACK段,
 4  * 客户端收到后从connect返回,同时应答一个ACK段,服务器收到后从accecpt()返回。
 5  * IPv4地址用sockaddr_in结构体表示,包括16位端口号和32位IP地址
 6  * IPv6地址用sockaddr_in6结构体表示,包括16位端口号和128位IP地址和一些控制字段
 7  * socket API可以接受各种类型的结构体指针做参数
 8  * 因为sock API的实现早于ANSI C标准化,那时还没有void  *类型,所以这些参数都用
 9  * struct sockaddr  *表示,所以在传递参数的时候要先转换下:
10  * int bind(int sockfd, const struct sockaddr *addr,
11  *              socklen_t addrlen);
12  *  使用:bind(listen_fd, (struct sockaddr *)&servaddr, sizeof(servaddr));
13  */
14 #include <sys/types.h>
15 #include <sys/socket.h>
16 #include <stdio.h>
17 #include <string.h>
18 #include <stdlib.h>
19 #include <arpa/inet.h>
20 #include <unistd.h>
21 #include <ctype.h>
22 
23 #define MAX_LINE 80
24 #define SERV_PORT 8000
25 int main()
26 {
27     //初始化客户端和服务端地址,因为是基于IPv4所以用sockaddr_in结构体
28     struct sockaddr_in servaddr, cliaddr;
29     socklen_t cliaddr_len;
30     int listenfd, connfd;
31     char buf[MAX_LINE];
32     int i, n;
33     //保存地址
34     char str[INET_ADDRSTRLEN];
35     //分配一个文件描述符:listenfd
36     listenfd = socket(AF_INET, SOCK_STREAM, 0);
37     //如果返回值小于0表示socket分配错误
38     if (listenfd < 0) {
39         perror("socket error\n");
40         exit(1);
41     }
42     
43     //先初始话地址用0填充
44     bzero( &servaddr, sizeof(servaddr) );
45     //设置地址类型为AF_INET
46     servaddr.sin_family = AF_INET;
47     //设置我网络地址为:INADDR_ANY,这个宏表示本地任意ip地址,htonl表示将32位的长整数从主机字节序转换为网络字节序
48     servaddr.sin_addr.s_addr = htonl( INADDR_ANY );
49     //设置端口号
50     servaddr.sin_port = htons(SERV_PORT);
51     //绑定文件描述符到服务器地址端口:bind(listenfd,  服务器地址端口),  将sockaddr_in转换为sockaddr
52     bind( listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr) );
53     
54     //使listenfd成为一个监听描述符:listen (listenfd, 连接队列长度)
55     listen(listenfd, 20);
56     printf("Accepting connections ...\n");
57     while (1) {
58         //阻塞等待客户端链接:connfd = accept(listenfd, 客户端地址端口, 长度)
59         cliaddr_len = sizeof(cliaddr);
60         //accept返回分配新的描述符connfd和客户端通信
61         connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len);
62         
63         //循环多次:阻塞等待客户端数据请求:read(connfd, buf, size)
64         n = read(connfd, buf, MAX_LINE);
65         //将地址转换为字符串
66         printf("received from %s at PORT %d\n", inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)), ntohs(cliaddr.sin_port));
67         //read返回等待处理客户端请求
68         for (i = 0; i < n; i++) {
69             //将所有字符转换为大写
70             buf[i] = toupper(buf[i]);
71         }
72         write(connfd, buf, n);
73         //关闭
74         close(connfd);
75     }
76     //循环多次结束:发送数据应答write(connfd, buf, size)
77     return 1;
78 }

客户端:

 1 /*client.c*/
 2 #include <stdio.h>
 3 #include <stdlib.h>
 4 #include <string.h>
 5 #include <unistd.h>
 6 #include <sys/socket.h>
 7 #include <netinet/in.h>
 8 #include <arpa/inet.h>
 9 
10 #define MAX_LINE 80
11 #define SERV_PORT 8000
12 
13 int main(int argc, char *argv[])
14 {
15     struct sockaddr_in servaddr;
16     char buf[MAX_LINE];
17     int sockfd, n, con;
18     char *str;
19     
20     if ( argc != 2 ) {
21         fputs("usage: ./client message\n", stderr);
22         exit(1);
23     }
24     str = argv[1];
25     
26     sockfd = socket(AF_INET, SOCK_STREAM, 0);
27     
28     bzero( &servaddr, sizeof(servaddr) );
29     servaddr.sin_family = AF_INET;
30     inet_pton (AF_INET, "127.0.0.1", &servaddr.sin_addr);
31     servaddr.sin_port = htons(SERV_PORT);
32     
33     con = connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr) );
34     if (con < 0) {
35         perror("connect error!\n");
36         exit(1);
37     }
38     write( sockfd, str, strlen(str));
39     
40     n = read(sockfd, buf, MAX_LINE);
41     printf("Response from server:\n");
42     write(STDOUT_FILENO, buf, n);
43     printf("\n");
44     close(sockfd);
45     
46     return 1;
47 }

博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3