首页 > 代码库 > 面向连接的echo服务编程实例
面向连接的echo服务编程实例
以下是echo_serv.c的源码,提供创建服务端,绑定套接字到本机IP的8080端口,当收到客户端发送的字符串就在屏幕上打印出来,并且把字符串发送给客户端
1 // echo_serv.c – gcc –o s echo_serv.c 2 #include <sys/types.h> 3 #include <sys/socket.h> 4 #include <netinet/in.h> 5 #include <arpa/inet.h> 6 #include <unistd.h> 7 #include <stdio.h> 8 #include <errno.h> 9 10 #define EHCO_PORT 8080 11 #define MAX_CLIENT_NUM 10 12 13 int main() 14 { 15 int sock_fd; 16 struct sockaddr_in serv_addr; 17 int clientfd; 18 struct sockaddr_in clientAdd; 19 char buff[101]; 20 socklen_t len; 21 int closing =0; 22 int n; 23 24 /* 创建socket */ 25 sock_fd = socket(AF_INET, SOCK_STREAM, 0); 26 if(sock_fd==-1) { 27 perror("create socket error!"); 28 return 0; 29 } else { 30 printf("Success to create socket %d\n", sock_fd); 31 } 32 33 /* 设置server地址结构 */ 34 bzero(&serv_addr, sizeof(serv_addr)); // 初始化结构占用的内存 35 serv_addr.sin_family = AF_INET; // 设置地址传输层类型 36 serv_addr.sin_port = htons(EHCO_PORT); // 设置监听端口 37 //serv_addr.sin_addr.s_addr = htons(INADDR_ANY); // 设置服务器地址 //用这个不能实现在不同主机上的通讯 38 serv_addr.sin_addr.s_addr = inet_addr("192.168.13.145"); // 设置服务器地址 39 40 bzero(&(serv_addr.sin_zero), 8); 41 42 /* 把地址和套接字绑定 */ 43 if(bind(sock_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr))!= 0) { 44 printf("bind address fail! %d\n", errno); 45 close(sock_fd); 46 return 0; 47 } else { 48 printf("Success to bind address!\n"); 49 } 50 51 /* 设置套接字监听 */ 52 if(listen(sock_fd ,MAX_CLIENT_NUM) != 0) { 53 perror("listen socket error!\n"); 54 close(sock_fd); 55 return 0; 56 } else { 57 printf("Success to listen\n"); 58 } 59 60 /* 创建新连接对应的套接字 */ 61 len = sizeof(clientAdd); 62 clientfd = accept(sock_fd, (struct sockaddr*)&clientAdd, &len); 63 if (clientfd<=0) { 64 perror("accept() error!\n"); 65 close(sock_fd); 66 return 0; 67 } 68 69 /* 接收用户发来的数据 */ 70 while((n = recv(clientfd,buff, 100,0 )) > 0) { 71 buff[n] = ‘\0‘; // 给字符串加入结束符 72 printf("number of receive bytes = %d data = http://www.mamicode.com/%s/n", n, buff); // 打印字符串长度和内容 73 fflush(stdout); 74 send(clientfd, buff, n, 0); // 发送字符串内容给客户端 75 if(strncmp(buff, "quit", 4) == 0) // 判断是否是退出命令 76 break; 77 } 78 79 close(clientfd); // 关闭新建的连接 80 close(sock_fd); // 关闭服务端监听的socket 81 82 return 0; 83 }
然后是客户端程序,在和服务器建立连接后发送字符串到服务器端,并且接受服务器发送的字符串显示在屏幕上
1 // echo_client – gcc –o c echo_client.c 2 #include <sys/types.h> 3 #include <sys/socket.h> 4 #include <netinet/in.h> 5 #include <arpa/inet.h> 6 #include <unistd.h> 7 #include <stdio.h> 8 #include <errno.h> 9 10 #define EHCO_PORT 8080 11 #define MAX_COMMAND 5 12 13 int main() 14 { 15 int sock_fd; 16 struct sockaddr_in serv_addr; 17 18 char *buff[MAX_COMMAND] = {"abc", "def", "test", "hello", "quit"}; 19 char tmp_buf[100]; 20 socklen_t len; 21 int n, i; 22 23 /* 创建socket */ 24 sock_fd = socket(AF_INET, SOCK_STREAM, 0); 25 if(sock_fd==-1) { 26 perror("create socket error!"); 27 return 0; 28 } else { 29 printf("Success to create socket %d\n", sock_fd); 30 } 31 32 /* 设置server地址结构 */ 33 bzero(&serv_addr, sizeof(serv_addr)); // 初始化结构占用的内存 34 serv_addr.sin_family = AF_INET; // 设置地址传输层类型 35 serv_addr.sin_port = htons(EHCO_PORT); // 设置监听端口 36 //serv_addr.sin_addr.s_addr = htons(INADDR_ANY); // 设置服务器地址 //用这个不能实现在不同主机上的通讯 37 serv_addr.sin_addr.s_addr = inet_addr("192.168.13.145"); // 设置服务器地址 38 bzero(&(serv_addr.sin_zero), 8); 39 40 /* 连接到服务端 */ 41 if (-1==connect(sock_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr))) { 42 perror("connect() error!\n"); 43 close(sock_fd); 44 return 0; 45 } 46 printf("Success connect to server!\n"); 47 48 /* 发送并接收缓冲的数据 */ 49 for (i=0;i<MAX_COMMAND;i++) { 50 send(sock_fd, buff[i], 100, 0); // 发送数据给服务端 51 n = recv(sock_fd, tmp_buf, 100, 0); // 从服务端接收数据 52 tmp_buf[n] = ‘\0‘; // 给字符串添加结束标志 53 printf("data send: %s receive: %s\n", buff[i], tmp_buf); // 打印字符串 54 if (0==strncmp(tmp_buf, "quit", 4)) // 判断是否是退出命令 55 break; 56 } 57 58 close(sock_fd); // 关闭套接字 59 60 return 0; 61 }
关于htos补充一下,也是摘自其它博主的吧
在C/C++写网络程序的时候,往往会遇到字节的网络顺序和主机顺序的问题。这是就可能用到htons(), ntohl(), ntohs(),htons()这4个函数。
网络字节顺序与本地字节顺序之间的转换函数:
htonl()--"Host to Network Long"
ntohl()--"Network to Host Long"
htons()--"Host to Network Short"
ntohs()--"Network to Host Short"
之所以需要这些函数是因为计算机数据表示存在两种字节顺序:NBO与HBO
网络字节顺序NBO(Network Byte Order): 按从高到低的顺序存储,在网络上使用统一的网络字节顺序,可以避免兼容性问题。
主机字节顺序(HBO,Host Byte Order): 不同的机器HBO不相同,与CPU设计有关,数据的顺序是由cpu决定的,而与操作系统无关。
如 Intel x86结构下, short型数0x1234表示为34 12, int型数0x12345678表示为78 56 34 12
如 IBM power PC结构下, short型数0x1234表示为12 34, int型数0x12345678表示为12 34 56 78
由于这个原因不同体系结构的机器之间无法通信,所以要转换成一种约定的数序,也就是网络字节顺序,其实就是如同power pc那样的顺序. 在PC开发中有ntohl和htonl函数可以用来进行网络字节和主机字节的转换.
说白了其实不过只是大端方式小端方式的转换
面向连接的echo服务编程实例