C语言实现基于TCP协议的C/S模型

基于TCP协议的C/S模型

 

编程模型:

 

        serve:           client:    
创建套接字(socket) 创建套接字(socket)

准备本机地址(sockaddr_in)    

准备目标机地址

绑定(bind)    

 
监听/宣告愿意连接(listen)  
等待连接/获取连接请求并建立连接(accept fork)     连接(connect)
接收请求(read/recv)   发送请求(write/send)
响应请求(write/send)   接收响应(read/recv)
关闭(close)         关闭(close)

先对使用socket进行TCP通信的几个函数做个说明:

#include 

int listen(int socket,int backlog);

功能: 宣告它愿意接收连接请求/设置等待连接的最大数量
sockfd: 被监听的套接字描述符
backlog: 提示系统该进程所要入队的未完成连接请求的数量
返回值: 成功返回0,失败返回,-1
注:一旦服务器调用了listen,套接字就能接收连接请求
#include 

int accept(int socket,struct sockaddr *addr,socklen_t *addrlen);

功能:获取连接请求并建立连接
addr:获取连接的地址
addrlen:设置连接地址结构体的长度
返回值:专门用于通信的描述符,该描述符连接到调用connect的客户端,这个新的套接字描述符和原始描述符具有相同的类型和地址族
int bind(int sockfd,const strucr sockaddr *addr,socklen_t addrlen);

sockfd:sockfd描述符:socket函数的返回值
addr:通信地址结构体,实际给的是sockaddr_un 或 sockaddr_in 需要强制类型转换。
addrlen:通信地址结构体类型的字节数,使用sizeof计算。
int connect(int sockfd,const struct sockaddr *addr,socklen_t addrlen);

功能:在请求服务的进程套接字(客户端)和提供服务的进程套接字(服务器)之间建立连接
sockfd:套接字描述符
addr:通信目标地址
addrlen:通信地址结构体类型的字节数,使用sizeof计算。
返回值:在不同的编程模型下返回值意义不同,在本地通信返回加0,失败返回-1。

附上具体的实现代码

/**服务器端代码(Linux下)**/
#include 
#include 
#include 
#include 
#include 
#include 

int main()
{
	puts("创建套结字");
	int sockfd = socket(AF_INET,SOCK_STREAM,0);
	if(0 > sockfd)
	{
		perror("socket");
		return -1;
	}
	puts("准备地址");
	struct sockaddr_in addr = {};
	addr.sin_family = AF_INET;
	addr.sin_port = htons(6677);
	addr.sin_addr.s_addr = inet_addr("10.0.2.15");
	socklen_t len = sizeof(addr);

	puts("绑定地址");
	if(bind(sockfd,(struct sockaddr*)&addr,len))
	{
		perror("bind");
		return -1;
	}
	
	puts("设置监听");
	if(listen(sockfd,5))
	{
		perror("listen");
		return -1;
	}

	puts("等待连接");
	for(;;)
	{
		struct sockaddr_in addrcli = {};
		socklen_t lencli = sizeof(addrcli);
		int clifd = accept(sockfd,(struct sockaddr*)&addrcli,&lencli);
		if(0 > clifd)
		{
			perror("accept");
			continue;
		}

		if(0 == fork())
		{
			//回声服务器
			char buf[1024] = {};
			for(;;)
			{
				read(clifd,buf,sizeof(buf));
				printf("read:%s fromip:%s\n",buf,inet_ntoa(addrcli.sin_addr));
				write(clifd,buf,strlen(buf)+1);
				if(0 == strcmp("quit",buf))
				{
					close(sockfd);
					close(clifd);
					return 0;
				}
			}
		}
	}
}
/**客户端代码(Linux下)**/
#include 
#include 
#include 
#include 
#include 
#include 
#include 

int main()
{
	puts("客户端创建socket");
	int sockfd = socket(AF_INET,SOCK_STREAM,0);
	if(0 > sockfd)
	{
		perror("socket");
		return -1;
	}
	puts("准备地址");
	struct sockaddr_in addr = {};
	addr.sin_family = AF_INET;
	addr.sin_port = htons(6677);
	addr.sin_addr.s_addr = inet_addr("10.0.2.15");
	socklen_t len = sizeof(addr);
	puts("连接服务器");
	if(connect(sockfd,(struct sockaddr*)&addr,len))
	{
		perror("connect");
		return -1;
	}
	char buf[1024] = {};
	for(;;)
	{
		printf("someone:");
		gets(buf);
		write(sockfd,buf,strlen(buf)+1);
		if(0 == strcmp("quit",buf))
		{
			puts("通信结束");
			break;
		}
		printf("read:");
		read(sockfd,buf,sizeof(buf));
		printf("%s\n",buf);
	}
	close(sockfd);
}

 

你可能感兴趣的:(C语言实现基于TCP协议的C/S模型)