【UNP学习笔记】一个简单的服务器/客户端程序
来源:互联网 发布:信用卡账单修改软件 编辑:程序博客网 时间:2024/05/16 23:33
照着书上的代码写了一个简单的socket程序,实现的功能是客户端向服务器发送一个字符串,服务器向客户端返回字符串的大小。写这个程序主要目的是熟悉基本的socket函数的使用,以及学习使用makefile。
测试时发现了一个有趣的现象:关闭服务器程序后,如果马上再次运行服务器程序就会返回bind error错误。这是由于关闭程序后TCP连接并没有马上终止,而是要执行TCP“四次挥手”,这时的服务器端处于TIME_WAIT状态,所以此时的端口仍然被占用。这时候如果立即执行服务器程序,bind函数就会因为端口被占用而失败。所以要等待几分钟直到上一个TCP连接完全终止,然后再运行新的服务端程序。
下面贴上代码
tcp_server.c
#include <stdio.h>#include <stdlib.h>#include <strings.h>#include <sys/types.h>#include <sys/socket.h>#include <arpa/inet.h>#include <unistd.h>#define PORT 8888 //侦听端口地址#define BACKLOG 2 //侦听队列长度void process_conn_server(int s);int main(int argc, char *argv[]){ int ss, sc; struct sockaddr_in server_addr; struct sockaddr_in client_addr; int err; pid_t pid; //建立一个流式套接字 ss = socket(AF_INET, SOCK_STREAM, 0); if(ss < 0){ printf("socket error\n"); return -1; } //设置服务器地址 bzero(&server_addr, sizeof(server_addr)); //清零 server_addr.sin_family = AF_INET; //地址族 server_addr.sin_addr.s_addr = htonl(INADDR_ANY); //本地地址 server_addr.sin_port = htons(PORT); //服务器端口 //绑定地址到套接字 err = bind(ss, (struct sockaddr*)&server_addr, sizeof(server_addr)); if(err < 0){ printf("bind error\n"); return -1; } //设置侦听 err = listen(ss, BACKLOG); if(err < 0){ printf("listen error\n"); return -1; } //主循环 for(;;){ socklen_t addrlen = sizeof(struct sockaddr); sc = accept(ss, (struct sockaddr*)&client_addr, &addrlen); if(sc < 0){ continue; } //建立新进程处理到来的连接 pid = fork(); if(pid == 0){ close(ss); process_conn_server(sc); }else{ close(sc); } }}
tvp_client.c
#include <stdio.h>#include <stdlib.h>#include <strings.h>#include <sys/types.h>#include <sys/socket.h>#include <arpa/inet.h>#include <unistd.h>#define PORT 8888void process_conn_client(int s);int main(int argc, char* argv[]){ int s; struct sockaddr_in server_addr; //服务器地址结构 s = socket(AF_INET, SOCK_STREAM, 0); //建立流式套接字 if(s < 0){ printf("socket error"); return -1; } //设置服务器地址 bzero(&server_addr, sizeof(server_addr)); server_addr.sin_family = 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); //关闭连接 return 0;}
tcp_process.c
#include <stdio.h>#include <string.h>#include <unistd.h>//服务器对客户端的处理void process_conn_server(int s){ ssize_t size = 0; char buffer[1024]; //数据缓冲区 for(;;){ size = read(s, buffer, 1024); //从套接字读取数据到缓冲区 if(size == 0) return; //构建响应字符,为接收到客户端字节的数量 sprintf(buffer, "%ld bytes altogether\n", 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); //写入到标准输出 } }}
Makefile文件
all:client serverclient:tcp_process.o tcp_client.o gcc -o client tcp_process.o tcp_client.oserver:tcp_process.o tcp_server.o gcc -o server tcp_process.o tcp_server.otcp_process.o: gcc -c tcp_process.c -o tcp_process.oclean: rm -f client server *.o
阅读全文
0 0
- 【UNP学习笔记】一个简单的服务器/客户端程序
- libevent实现的一个简单的服务器和客户端程序
- 用Java实现一个简单的服务器与客户端程序
- 使用jrtplib写的一个简单服务器和客户端程序
- 用Java实现一个简单的服务器与客户端程序
- Python一个简单的通信程序(客户端 服务器)
- 一个简单的时间获取客户端——服务器程序
- 一个简单的时间获取客户端/服务器程序
- python笔记-Twisted 实现简单的服务器客户端程序
- UNIX环境编程学习笔记-----编程实例------一个简单的服务器端和客户端程序
- RakNet最简单的服务器客户端程序
- 简单的客户端服务器通信程序
- 简单的客户端和服务器通信程序
- 简单的socket 服务器/客户端 程序
- 简单的时间/日期客户端&服务器程序
- UNP函数笔记三: TCP客户/服务器程序示例
- 一个简单的IOCP服务器/客户端类
- 一个简单的客户端-服务器模型
- 2017年10月17日-ACM涉及知识需掌握
- SpringBoot自定义静态资源映射方法
- swift脚本编程:一键生成AppIcon
- idea intellij main方法 [public static void main(String[] args) 快速生成]
- 字符串的大小比较
- 【UNP学习笔记】一个简单的服务器/客户端程序
- Spring boot 使用 Redis 缓存
- 12,mac phpstorm xdebug
- Unity3D基于陀螺仪实现VR相机功能
- 常用数据结构与算法
- 【Python-3.5】绘制随机漫步图
- bzoj 4002: [JLOI2015]有意义的字符串(特征根法+矩阵快速幂)
- linux下内核模块的加载与卸载
- hibernatetools-Update-4.1.1.Final插件安装