TCP客户/服务器程序示例
这一章信息量开始大起来了,粗略来看它实现了简单的TCP客户/服务器程序,里面也有一些费解的细节。
1.概述
完整的TCP客户/服务器程序示例。这个简单的例子将执行如下步骤的一个回射服务器(这里的回射服务器就是服务简单的把客户端发送的消息返回给客户):
1)客户从标准输入读入一行文本,并写给服务器
2)服务器从网络输入读入这行文本,并回射给客户
3)客户从网络输入读入这行回射文本,并显示在标准输出上
这样实际上就构成了一个全双工的TCP连接。
本章就围绕了这个简单的TCP客户/服务器程序做了一些扩展:比如信号处理问题,启动和终止时TCP分节发送,服务器崩溃等等。
2.TCP回射服务器程序
2.1 main函数
书中为了方便读者忽略写代码时的繁文缛节,对socket函数和I/O函数都做了包裹,这样摒弃了一些细节,便于理解,当然缺点也是显而易见,咱们在工作或者项目时,不可能把书中的那一套东西一直出来(这将是个体力活儿),毕竟talk is cheap show me the code,打算自己把书中的包裹函数拆开,写写试试。
//testserv.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <stdio.h>
#include <netinet/in.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#define MAXLEN 1024
#define SERV_PORT 1024 // 1024~49151未被使用的端口
void echo_str(int);//回射函数声明
int main(int argc,char *argv[])
{
struct sockaddr_in serveraddr; //服务器套接字结构
struct sockaddr_in cliaddr;//客户端套接字结构
int listenfd;//监听套接字描述符
int connfd; //连接套接字字描述符
pid_t pid_id; //进程号
//初始化
memset(&serveraddr,0x00,sizeof(serveraddr));
memset(&cliaddr,0x00,sizeof(cliaddr));
//填写套接字结构
serveraddr.sin_family=AF_INET;//协议族
serveraddr.sin_addr.s_addr=htonl(INADDR_ANY);//监听任意IP
serveraddr.sin_port=htons(SERV_PORT);//监听1024端口号
if((listenfd=socket(AF_INET,SOCK_STREAM,0))<0)//创建套接字
{
printf("socket error\r\n");
return -1;
}
if(bind(listenfd,(struct sockaddr *)&serveraddr,sizeof(serveraddr))<0)//绑定套接字
{
printf("bind error\r\n");
return -1;
}
if(listen(listenfd,5)<0)//监听套接字
{
printf("listen error\r\n");
return -1;
}
while(1)
{
connfd=accept(listenfd,NULL,NULL);
if(0==(pid_id=fork()))//子进程处理
{
close(listenfd);
echo_str(connfd);//回射函数
return 0;
}
close(connfd);
}
}
这里唯一需要注意的地方在前面章节介绍过,由于创建子进程后,监听套接字和已连接套接字的引用计数会由于子进程的拷贝分别增加,这时候在要在主进程中关闭已连接套接字,在子进程中关闭监听套接字。
2.2 str_echo回射函数
回射函数在子进程中调用,因为他的功能就是读取(read)客户端的数据,并将数据回射(write)给客户。
//testsrv.c
void echo_str(int connfd)
{
ssize_t nread;
char readbuff[MAXLEN];
memset(readbuff,0x00,sizeof(readbuff));
while((nread=read(connfd,readbuff,MAXLEN))>0)//读取数据
{
write(connfd,readbuff,strlen(readbuff));//回射数据
memset(readbuff,0x00,sizeof(readbuff));
}
}
3.TCP回射客户程序
3.1 main函数
//testcli.c