转载:linux-echo服务器_雨夜聆风的专栏-CSDN博客
写在文章前:
echo服务器,可以看成 学习网络编程的“hello world”。
echo服务器,描述起来很简单,服务端收到什么,就给客户端发送什么。也就是这个简单的程序,能够让你从中学到不少东西。多线程,多进程,I/O复用,信号处理这些都会遇到。
第一个echo服务程序,不需要考虑各种问题,只要能够完成功能就行。
先来看看简易流程图
基于TCP Socket编程的流程图类似,服务端主要是,创建socket、绑定IP和端口、监听、接受连接、处理数据包、关闭连接。客户端则主要是,创建socket、连接到服务器、发送请求、关闭连接。
echo服务端代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78/* * File: Server.c * Author: root * * Created on 2012年6月20日, 下午1:29 */ #include <stdio.h> #include <stdlib.h> #include <sys/socket.h> #include <string.h> #include <errno.h> #include <netinet/in.h> #include <arpa/inet.h> #define SERVERIP "192.168.0.23" #define SERVERPORT 12345 #define MAXBUFFER 256 int main(int argc, char** argv) { int serverFd, connfd,ret; socklen_t len; struct sockaddr_in serveraddr,clientaddr; char readBuf[MAXBUFFER]={0}; char ip[40]={0}; serverFd=socket(AF_INET,SOCK_STREAM,0);//创建socket if(serverFd < 0) { printf("socket error:%sn",strerror(errno)); exit(-1); } bzero(&serveraddr,sizeof(serveraddr)); serveraddr.sin_family=AF_INET; serveraddr.sin_port=htons(SERVERPORT); inet_pton(AF_INET,SERVERIP,&serveraddr.sin_addr);//将c语言字节序转换为网络字节序 ret=bind(serverFd,(struct sockaddr *)&serveraddr,sizeof(serveraddr));//绑定IP和端口 if(ret!=0) { close(serverFd); printf("bind error:%sn",strerror(errno)); exit(-1); } ret=listen(serverFd,5);//监听 if(ret!=0) { close(serverFd); printf("listen error:%sn",strerror(errno)); exit(-1); } len=sizeof(clientaddr); bzero(&clientaddr,sizeof(clientaddr)); while (1) { connfd = accept(serverFd, (struct sockaddr *) &clientaddr, &len);//接受客户端的连接 printf("%s 连接到服务器 n",inet_ntop(AF_INET,&clientaddr.sin_addr,ip,sizeof(ip))); if (serverFd < 0) { printf("accept error : %sn", strerror(errno)); continue; } while((ret=read(connfd,readBuf,MAXBUFFER)))//读客户端发送的数据 { write(connfd,readBuf,MAXBUFFER);//写回客户端 bzero(readBuf,MAXBUFFER); } if(ret==0) { printf("客户端关闭连接n"); }else { printf("read error:%sn",strerror(errno)); } close(connfd); } close(serverFd); return 0; }
echo 客户端代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53/* * File: Client.c * Author: root * * Created on 2012年6月20日, 下午1:30 */ #include <stdio.h> #include <stdlib.h> #include <sys/socket.h> #include <string.h> #include <errno.h> #include <netinet/in.h> #include <arpa/inet.h> #define SERVERIP "192.168.0.23" #define SERVERPORT 12345 #define MAXBUFFER 256 int main(int argc, char** argv) { int clientFd,ret; struct sockaddr_in serveraddr; char buf[MAXBUFFER]; clientFd=socket(AF_INET,SOCK_STREAM,0);//创建socket if(clientFd < 0) { printf("socket error:%sn",strerror(errno)); exit(-1); } bzero(&serveraddr,sizeof(serveraddr)); serveraddr.sin_family=AF_INET; serveraddr.sin_port=htons(SERVERPORT); inet_pton(AF_INET,SERVERIP,&serveraddr.sin_addr); ret=connect(clientFd,(struct sockaddr *)&serveraddr,sizeof(serveraddr));//连接到服务器 if(ret!=0) { close(clientFd); printf("connect error:%sn",strerror(errno)); exit(-1); } while(1) { bzero(buf,sizeof(buf)); scanf("%s",buf); write(clientFd,buf,sizeof(buf));//写数据 bzero(buf,sizeof(buf)); read(clientFd,buf,sizeof(buf));//读数据 printf("echo:%sn",buf); } close(clientFd); return (EXIT_SUCCESS); }
执行效果图:
在这里需要注意一个问题:网络字节序问题
内存中存储字节有两种方式,一种是小端字节序(低序字节储存在起始地址),第二种是大端字节序(高位字节存储在起始地址)。而且这两种字节序都有在使用。当两台机器通信时,为了避免字节序之间转换问题,系统提供了4个函数
#include<netinet/in.h>
uint32_t ntohl (uint32_t __netlong) ;
uint16_t ntohs (uint16_t __netshort);
uint32_t htonl (uint32_t __hostlong);
uint16_t htons (uint16_t __hostshort);
用这个程序说明一下,ctrl-z,ctrl-c,ctrl-d的差别
ctrl-c 发送 SIGINT 信号给前台进程组中的所有进程。常用于终止正在运行的程序。
从上面那个图可以看出,ctrl+c终止客户端程序
ctrl-z 发送 SIGTSTP 信号给前台进程组中的所有进程,常用于挂起一个进程。
ctrl+z,将程序挂起。fg命令重新启动前台被中断的任务,bg命令把被中断的任务放在后台执行.
ctrl-d 不是发送信号,而是表示一个特殊的二进制值,表示 EOF。
程序不足之处:
- 服务端只能同时响应一个用户请求。可以采用多线程解决
- 服务端异常退出,客户端无法立即响应。采用I/O复用解决
最后
以上就是大方电脑最近收集整理的关于linux-echo服务器的全部内容,更多相关linux-echo服务器内容请搜索靠谱客的其他文章。
发表评论 取消回复