winsock网络编程1——Echo客户/服务器程序

       网络结构模型主要有两种,分布式和集中式。而分布式又分为客户/服务器模型和对等网络模型。

       网络模型中的集中式系统的优点是结构简单,安全性好,终端廉价,缺点会对主机造成很大压力,且不能对不同用户进行单独的相应的配置,主要应用实例有自动取款机(ATM)、超市收款机(POS)等。

      而分布式系统具有高度的可靠性、均衡负载且能满足不同的需求。分布式中的对等网络模型又可细分为无结构网络、有结构网络、混合式网络和集中式网络。客户服务器模型可以细分为平坦模型和层次模型。平坦模型中所有客户都与一个服务器通信;层次模型中的一个等级的主机是低一级的主机的服务器,同时也作为高一级主机的客户端。

     客户/服务器模型是分布式系统中使用最广泛的网络模型,许多商业软件都使用客户/服务器模型,重要的应用层协议也是基于该模型设计的,如HTTP、FTP、DNS、Telnet等。

     以下是一个用Winsock模拟的Echo服务器程序和客户端程序。首先介绍以下Echo。Echo是互联网上的一个标准的协议,它是一个非常有用的调试和测试工具,Echo服务器简单地把它接受到的任何信息发回给客户端,它既可以使用TCP,也可以使用UDP协议,知名端口号是7。下面将基于TCP来实现这个协议。

     服务器端程序:

#include<stdio.h>
#include<winsock2.h>

#pragma comment(lib, "ws2_32")  /*winsock 使用的库函数*/
 
#define ECHO_DEF_PORT  7   /*侦听的默认端口*/
#define ECHO_BUF_SIZE  256  /*缓冲区的大小*/

int main(int argc, char **argv)
{	
	WSADATA wsa_data;
	SOCKET echo_soc = 0,    /*侦听socket句柄*/
		acpt_soc;

	struct sockaddr_in serv_addr,   /*socket的本地地址*/
						clnt_addr;   /*socket的远端地址*/
	unsigned short port = ECHO_DEF_PORT;
	int result = 0;
	int addr_len = sizeof(struct sockaddr_in);
	char recv_buf[ECHO_BUF_SIZE];

	if(argc == 2)
	{
		port = atoi(argv[1]);
	}

	WSAStartup(MAKEWORD(2,0), &wsa_data);   /*初始化winsock资源*/
	echo_soc = socket(AF_INET, SOCK_STREAM, 0);

	/*socket的本地地址*/
	serv_addr.sin_family = AF_INET;
	serv_addr.sin_port = htons(port);
	serv_addr.sin_addr.S_un.S_addr = INADDR_ANY;

	result = bind(echo_soc, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
	if(result == SOCKET_ERROR)
	{
		printf("[Echo Server] bind error:%d\n", WSAGetLastError());
		closesocket(echo_soc);
		return -1;
	}

	listen(echo_soc, SOMAXCONN);

	printf("[Echo server] is running……\n");
	while(1)
	{
		acpt_soc = accept(echo_soc, (struct sockaddr*)&clnt_addr, &addr_len);
		if(acpt_soc == INVALID_SOCKET)
		{
			printf("[Echo Server] accept error:%d\n", WSAGetLastError());
			break;
		}

		result = recv(acpt_soc, recv_buf, ECHO_BUF_SIZE, 0);
		if(result > 0)
		{
			recv_buf[result] = 0;
			printf("[Echo Server] receives:\"%s\", from %s\r\n", recv_buf, inet_ntoa(clnt_addr.sin_addr));
			result = send(acpt_soc, recv_buf, result, 0);
		}

		closesocket(acpt_soc);
	}

	closesocket(echo_soc);
	WSACleanup();

	return 0;
}
     客户端程序:

#include<stdio.h>
#include<winsock2.h>   /*winsock2.h 已经包含windows.h*/

#pragma comment(lib, "ws2_32")   /*加载winsock库函数的动态链接库*/

#define ECHO_DEF_PORT   7     /*连接的默认端口*/
#define ECHO_BUF_SIZE   256   /*缓冲区的大小*/


int main(int argc, char **argv)
{
	WSADATA wsa_data;      /*接受加载进来的套接字库的版本信息*/
	SOCKET echo_soc = 0;   /*socket句柄*/
	struct sockaddr_in serv_addr;   /*服务器地址*/
	unsigned short port = ECHO_DEF_PORT;
	int result = 0, send_len = 0;
	char *test_data = "Hello world!", recv_buf[ECHO_BUF_SIZE];

	if(argc < 2)
	{
		printf("input %s server_address [port]\n", argv[0]);
		return -1;
	}
	if(argc >=3)
	{
		port = atoi(argv[2]);
	}

	WSAStartup(MAKEWORD(2,0), &wsa_data);  /*初始化winsock资源*/
	send_len = strlen(test_data);

	/*服务器地址*/
	serv_addr.sin_family = AF_INET;
	serv_addr.sin_port = htons(port);   /*转为网络字节序*/
	serv_addr.sin_addr.S_un.S_addr = inet_addr(argv[1]);  /*将用ascii表示的IP地址转换无二进制地址*/

	if(serv_addr.sin_addr.S_un.S_addr == INADDR_NONE)    
	{
		printf("[ECHO] invalid address\n");
		return -1;
	}

	echo_soc = socket(AF_INET, SOCK_STREAM, 0);   /*创建socket*/
	result = connect(echo_soc, (struct sockaddr*)&serv_addr, sizeof(serv_addr));

	if(result == 0)  /*连接成功*/
	{
		result = send(echo_soc, test_data, send_len, 0);      
		result = recv(echo_soc, recv_buf, ECHO_BUF_SIZE, 0);   /*返回接受到的字节数*/
	}

	if(result > 0)
	{
		recv_buf[result] = 0;    /*为字符串添加结束符null*/
		printf("[Echo Client] receives:\"%s\"\r\n", recv_buf);
	}
	else
	{
		printf("[Echo Client] error:%d.\r\n", WSAGetLastError());
	}

	closesocket(echo_soc);
	WSACleanup();

	return 0;
}



你可能感兴趣的:(c,网络编程,winsock)