说明:
本文章旨在总结备份、方便以后查询,由于是个人总结,如有不对,欢迎指正;另外,内容大部分来自网络、书籍、和各类手册,如若侵权请告知,马上删帖致歉。
QQ 群 号:513683159 【相互学习】
内容来源:
《Linux网络编程》
客户端连接服务器后从标准输入读取字符串发送给服务器。
服务器接收到字符串后,发送接收到的总字符串个数给客户端、
客户端将接受到的服务器信息打印到标准输出。
整个过程流程如下:
#include客户端源文件:tcp_client.c#include #include #include #include #include #include #define PORT 8888 //侦听端口地址:8888 #define BACKLOG 2 //侦听队列长度:2 extern void process_conn_server(int s); //服务器对客户端的处理:读取数据并发送响应字符 int main(int argc,char *argv[]) { int ss = 0; //ss = server socket = 服务器socket描述符 int cs = 0; //cs = client socket = 客户端socket描述符 struct sockaddr_in server_addr; //服务器地址结构 struct sockaddr_in client_addr; //客户端地址结构 int ret = 0; //返回值 pid_t pid; //进程ID ss = socket(AF_INET,SOCK_STREAM,0); //创建一个AF_INET族的流类型socket if(ss < 0) //检查是否正常创建socket { perror("socket errorn"); exit(EXIT_FAILURE); } bzero(&server_addr,sizeof(server_addr)); //清零 server_addr.sin_family = AF_INET; //设置地址族为AF_INET server_addr.sin_addr.s_addr = htonl(INADDR_ANY); //本地地址 server_addr.sin_port = htons(PORT); //设置端口号 ret = bind(ss,(struct sockaddr*)&server_addr,sizeof(server_addr)); if (ret < 0) //出错 { perror("bind errorn"); exit(EXIT_FAILURE); } ret = listen(ss,BACKLOG); if (ret < 0) //出错 { perror("bind errorn"); exit(EXIT_FAILURE); } for(;;) { int addrlen = sizeof(struct sockaddr); cs = accept(ss,(struct sockaddr*)&client_addr,&addrlen); if(cs < 0) //出错 { continue; //结束本次循环 } pid = fork(); //创建新进程 if(pid < 0) { printf("fork errorn"); } else if(pid == 0) { close(ss); //子进程中关闭服务器的侦听 process_conn_server(cs); //处理连接 } else { close(cs); //父进程中关闭客户端的连接 } } return 0; }
#include处理源文件:tcp_process.c#include #include #include #include #include #include #include #define PORT 8888 //端口地址:8888 extern void process_conn_client(int s); int main(int argc,char *argv[]) { int s = 0; //socket描述符 struct sockaddr_in server_addr; //服务器地址结构 int ret = 0; //返回值 s = socket(AF_INET,SOCK_STREAM,0); //创建一个AF_INET族的流类型socket if(s < 0) //检查是否正常创建socket { perror("socket errorn"); exit(EXIT_FAILURE); } bzero(&server_addr,sizeof(server_addr)); //清零 server_addr.sin_family = AF_INET; //设置地址族为AF_INET server_addr.sin_addr.s_addr = htonl(INADDR_ANY); //本地地址 server_addr.sin_port = htons(PORT); //设置端口号 inet_pton(AF_INET,argv[1],&server_addr.sin_addr); connect(s,(struct sockaddr*)&server_addr,sizeof(struct sockaddr)); process_conn_client(s); //客户端处理过程 close(s); //关闭连接 }
#includeMakefile文件#include #include void process_conn_server(int s) { ssize_t size = 0; char buffer[1024]; //数据的缓冲区 for (;;) //循环处理过程 { size = read(s,buffer,1024); //从套接字中读取数据放到缓冲区buffer中 if(size == 0) //没有数据 { return; } sprintf(buffer,"%ld bytes altogethern",size); write(s,buffer,strlen(buffer)+1); //发给客户端 } } void process_conn_client(int s) { ssize_t size = 0; char buffer[1024]; //数据的缓冲区 for(;;) { size = read(0,buffer,1024); if(size > 0) //读到数据 { write(s,buffer,size); //发送给服务器 size = read(s,buffer,1024); //从服务器读取数据 write(1,buffer,size); //写到标准输出,0表示标准输入,1表示标准输出 } } }
all:client server #all规则,依赖于client和server规则
client:tcp_process.o tcp_client.o #client规则,生成客户端可执行程序
gcc -o client tcp_process.o tcp_client.o
server:tcp_process.o tcp_server.o #server规则,生成服务器端可执行程序
gcc -o server tcp_process.o tcp_server.o
clean: #清理规则,删除client、server和中间文件
rm -f client server *.o
编译并运行
将上面文件全部置于同一目录下。
1️⃣编译:
执行命令:make,结果如下:
cc -c -o tcp_process.o tcp_process.c #生成tcp_process.o中间文件 cc -c -o tcp_client.o tcp_client.c #生成tcp_client.o中间文件 gcc -o client tcp_process.o tcp_client.o #由tcp_process.o与tcp_client.o生成可执行文件:client cc -c -o tcp_server.o tcp_server.c #生成tcp_server.o中间文件 gcc -o server tcp_process.o tcp_server.o #由tcp_process.o与tcp_server.o生成可执行文件:server
2️⃣运行:
①打开终端,执行命令:./server
会执行服务端可执行程序server,该程序会在端口8888上侦听,等待客户端的连接请求。
②另起终端,执行命令:./client 127.0.0.1
会执行服务端可执行程序client ,该程序会连接上服务器
紧接着输入字符串就会有相应,效果如下:
hhb@xsndz:/home/hhb/桌面/tcp$ ./client 127.0.0.1 nihao 6 bytes altogether shiyishi 9 bytes altogether查询网络连接情况
在程序正常运行的状态,再另起终端,使用netstat命令查询网络连接情况。
执行指令:netstat,效果如下:
激活Internet连接 (w/o 服务器) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 localhost:39460 localhost:8888 ESTABLISHED tcp 0 0 localhost:8888 localhost:39460 ESTABLISHED
其中8888为服务器端的端口,39460为客户端的端口
服务器和客户端段通过这两个端口建立了连接。



