TCP IP网络编程1 简单的回声服务器端、客户端
2016-04-25 14:18
573 查看
代码参考自《TCP IP 网络编程》
需要学习nginx,所以要先了解下web服务器编程的相关知识。
TCP服务器端需要依次调用socket() –> bind() –> listen() 以使服务器端处于等待连接请求的状态;
而后循环调用accept() 从请求队列中取出连接并生成和客户端相连接的socket,然后可以从此socket中读取数据或者向其写入数据以和客户端通信。
在读取或者写入数据的时候可以用标准I/O函数,也可以用Linux I/O函数。
Linux I/O函数:
用read从socket描述符中读取数据时
如果socket输入缓冲为空,没有数据,read操作会阻塞;
如果操作失败,则返回-1,并设置errno;
如果输入缓冲中已有数据,则最多读取count个字节,并返回实际读取的字节数(例如 TCP客户端通过write发送了2k数据,但是在当前只有1k传输到服务端的输入缓冲中,则read操作也会读取当前的1k数据并立即返回,因为TCP协议中是没有数据边界的);
如果读取到EOF,则返回0(例如 TCP客户端通过close或者shutdown方法关闭了相应的输出流,则会给服务端发送EOF)。
需要学习nginx,所以要先了解下web服务器编程的相关知识。
TCP服务器端需要依次调用socket() –> bind() –> listen() 以使服务器端处于等待连接请求的状态;
而后循环调用accept() 从请求队列中取出连接并生成和客户端相连接的socket,然后可以从此socket中读取数据或者向其写入数据以和客户端通信。
在读取或者写入数据的时候可以用标准I/O函数,也可以用Linux I/O函数。
Linux I/O函数:
#include <unistd.h> ssize_t read(int fd, void *buf, size_t count); ssize_t write(int fd, const void *buf, size_t count);
用read从socket描述符中读取数据时
如果socket输入缓冲为空,没有数据,read操作会阻塞;
如果操作失败,则返回-1,并设置errno;
如果输入缓冲中已有数据,则最多读取count个字节,并返回实际读取的字节数(例如 TCP客户端通过write发送了2k数据,但是在当前只有1k传输到服务端的输入缓冲中,则read操作也会读取当前的1k数据并立即返回,因为TCP协议中是没有数据边界的);
如果读取到EOF,则返回0(例如 TCP客户端通过close或者shutdown方法关闭了相应的输出流,则会给服务端发送EOF)。
//回声服务端 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> #define BUF_SIZE 1024 void error_handling(char *messages); int main(int argc, char *argv[]) { int serv_sock, clnt_sock; char messages[BUF_SIZE]; int str_len, i; struct sockaddr_in serv_adr, clnt_adr; socklen_t clnt_adr_sz; if(argc != 2) { printf("Usage : %s <port>\n", argv[0]); exit(1); } serv_sock = socket(PF_INET, SOCK_STREAM, 0); if(serv_sock == -1) error_handling("socket() error"); memset(&serv_adr, 0, sizeof(serv_adr)); serv_adr.sin_family = AF_INET; serv_adr.sin_addr.s_addr = htonl(INADDR_ANY); serv_adr.sin_port = htons(atoi(argv[1])); if(bind(serv_sock, (struct sockaddr*)&serv_adr, sizeof(serv_adr)) == -1) error_handling("bind() error"); if(listen(serv_sock, 10) == -1) error_handling("listen() error"); clnt_adr_sz = sizeof(clnt_adr); while(1) { clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_adr, &clnt_adr_sz); if(clnt_sock == -1) error_handling("accept() error"); else printf("Connected client %d \n", i + 1); while((str_len = read(clnt_sock, messages, BUF_SIZE)) != 0) write(clnt_sock, messages, str_len); close(clnt_sock); } close(serv_sock); return 0; } void error_handling(char *messages) { fputs(messages, stderr); fputc('\n', stderr); exit(1); }
//回声客户端,因为TCP数据传输没有边界,所以记录读取的数据长度,在读取到写入给服务器端的数据长度时停止 //一般情况下是无法预知需要读取的长度的,所以需要定义应用层协议,按照协议要求读写数据 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> #define BUF_SIZE 1024 void error_handling(char *message); int main(int argc, char *argv[]) { int sock; char message[BUF_SIZE]; int str_len, recv_len, recv_cnt; struct sockaddr_in serv_adr; if(argc != 3) { printf("Usage : %s <IP> <port>\n", argv[0]); exit(1); } sock = socket(PF_INET, SOCK_STREAM, 0); if(sock == -1) error_handling("socket() error"); memset(&serv_adr, 0, sizeof(serv_adr)); serv_adr.sin_family = AF_INET; serv_adr.sin_addr.s_addr = inet_addr(argv[1]); serv_adr.sin_port = htons(atoi(argv[2])); if(connect(sock, (struct sockaddr*)&serv_adr, sizeof(serv_adr)) == -1) error_handling("connect() error"); else puts("Connected........"); while(1) { fputs("Input message(Q to quit): ", stdout); fgets(message, BUF_SIZE, stdin); if(!strcmp(message, "q\n") || !strcmp(message, "Q\n")) break; str_len = write(sock, message, strlen(message)); recv_len = 0; while(recv_len < str_len) { recv_cnt = read(sock, &message[recv_len], BUF_SIZE - 1); if(recv_cnt == -1) error_handling("read() error"); recv_len += recv_cnt; } message[recv_len] = 0; printf("Message from server: %s", message); } close(sock); return 0; } void error_handling(char *message) { fputs(message, stderr); fputc('\n', stderr); exit(1); }
相关文章推荐
- TCP/IP网络体系结构
- 北京林业大学“计蒜客”杯程序设计竞赛 网络赛 马踏棋盘的问题
- ISO/OSI网络体系结构
- SSL构建单双向https认证
- 集成Vitamio来播放网络视频(支持多种格式解码)
- 使用XMLHttpRequest
- iOS9 HTTP 不能正常使用的解决办法
- HTTP 协议详解
- HTTPS那些事 用java实现HTTPS工作原理
- 网络安全,教你怎样做到反“作死”!
- iOS获取网络图片计算其大小
- nodejs 原生代码模拟express 框架 创建http server
- iOS网络编程 - 7
- TCP/IP 小知识
- python使用json web token (jwt)实现http api的加密传输
- iOS网络编程 - 6
- 4月28--30日:一起去北展揭开电信网络诈骗的神秘面纱
- Jmeter --- Http Cookie Manager
- TCP/IP 总结
- Jmeter -- HTTP Request Defaults