Winsocket通信测试

在学习网络编程之前,我们需要对Tcp/ip协议栈有个清楚地了解。Tcp/ip协议栈分以下五层,也有分成7层

 5、应用层
    4、传输层
    3、网络层
    2、数据链路层
    1、物理层

物理层是实实在在的物理链路,它为上层协议提供了一个传输数据的物理媒体,负责将数据以比特流的方式收发、接收。数据链路层主要负责物理传输的准备,MAC地址和交换机都工作在这一层。网络层主要负责管理网络地址、定位设备、决定路由。路由器就工作在这一层。作用是将网路地址翻译成物理地址,并决定将数据从发送方路由到接收方。应用层,一般是指应用程序,该层主要负责确定通信对象,并确保有足够资源用于通信。根据传输层的端口信息调用不同的程序来处理传输的内容,端口8080是http报文,端口21是ftp报文。

物理层关心的是如何把电气信号变成一段报文;数据链路层关心的是mac地址、vlan、优先级等;网络层关心的是ip地址,下一跳ip;传输层关心的是端口资源;应用层关心的是报文组装、解析、渲染、存储、执行等等。

在学习网络编程之前,学习socket的工作原理是很有必要的。我们需要为它配置端口信息和ip地址。配置完了之后,我们就可以慢慢等待报文的收发了。所以一般来说,作为服务器端口的处理流程是这样的:

 a) 创建socket
 b) 绑定socket到特定的ip地址
 c) 对socket进行侦听处理
 d) 接受socket,表明有客户端和服务器连接
 e) 和客户端循环收发报文
 f) 关闭socket
客户端的处理流程就相对简单一点了,只需要
a) 创建socket
b) 链接服务器端地址
c) 和服务器端的socket收发报文

一、Winsocket用TCP协议来完成通信


①服务器的程序

// SocketSever.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <Winsock2.h>
#include <stdio.h>
#include <stdlib.h>

#pragma comment(lib,"WS2_32.LIB")

#if DUBUG  
	#define AF_INET         2               /* internetwork: UDP, TCP, etc. */
	#define SOCK_STREAM     1               /* stream socket */
	#define SOCK_DGRAM      2               /* datagram socket */
	#define SOCK_RAW        3               /* raw-protocol interface */
	#define SOCK_RDM        4               /* reliably-delivered message */
	#define SOCK_SEQPACKET  5               /* sequenced packet stream */
	/*
	* Socket address, internet style.
	*/
	struct sockaddr_in {
			short   sin_family;
			u_short sin_port;
			struct  in_addr sin_addr;
			char    sin_zero[8];
	};
	typedef struct sockaddr_in SOCKADDR_IN; /* Microsoft Windows Extended data types */
	int bind(
		SOCKET s,
		const struct sockaddr FAR * name,
		int namelen
		);									/* INCL_WINSOCK_API_PROTOTYPES*/
	int listen(
		SOCKET s,
		int backlog
		);
#endif 

#define Port 3578
#define MaxSize 1024

SOCKADDR_IN addrSrv;
SOCKADDR_IN addrClient;
SOCKET sockSrv; //服务器

SOCKET sockConn;

//********************************************************************************************************/
//** 函数名 ** StartSock()
//**  输入  ** 无
//**  输出  ** 无
//**函数描述** 加载套接字
//********************************************************************************************************/
int SocketInit()
{
	WORD wVersionRequested;
	WSADATA wsaData;
	int err;

	wVersionRequested=MAKEWORD(2,2);
	err = WSAStartup(wVersionRequested,&wsaData); //返回0,成功,否则就是错误码

	if (err!=0)
	{
		printf("WinSock DLL版本不足要求n");
		return 0;
	}

	if (LOBYTE(wsaData.wVersion)!=2||
		HIBYTE(wsaData.wVersion)!=2)
	{
		WSACleanup();
		return 0;
	}

	return 1;
}

//********************************************************************************************************/
//** 函数名 ** main()
//**  输入  ** 无
//**  输出  ** 无
//**函数描述** 主函数
//********************************************************************************************************/
int main()
{
 	if (SOCKET_ERROR ==SocketInit())
 	{
 		return -1;
 	}
	
	SOCKADDR_IN addrSrv;//存放本地地址信息的
	addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY);//htol将主机字节序long型转换为网络字节序
	addrSrv.sin_family=AF_INET;
	addrSrv.sin_port=htons(6001);//htos用来将端口转换成字符,1024以上的数字即可
	
	//真正socket编程部分
	SOCKET sockSrv=socket(AF_INET,SOCK_STREAM,0);//面向连接的可靠性服务SOCK_STRAM
	bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));//将socket绑定到相应地址和端口上
	listen(sockSrv,5);//等待队列中的最大长度为5
	printf("%s\n","Welcome,the Host is running!Now Wating for someone comes in!");

	SOCKADDR_IN addrClient;
	int iSend = 0;
	char sendBuf[MaxSize];
	char revBuf[MaxSize];

	int len=sizeof(SOCKADDR);

	while(1)			//循环监听客户端,永远不停止
	{
		sockConn=accept(sockSrv,(SOCKADDR*)&addrClient,&len);//阻塞调用进程直至新的连接出现

		if(sockConn == INVALID_SOCKET)
		{
			printf("Accept Failed!\n");
			return -1;
		}

		sprintf(sendBuf,"Server IP is:%s",inet_ntoa(addrClient.sin_addr));//inet_nota函数是将字符转换成ip地址

		iSend = send(sockConn,sendBuf,strlen(sendBuf)+1,0);//服务器向客户端发送数据

		if(iSend == SOCKET_ERROR)
		{
			printf("send Failed!");
			break;
		}

		char recvBuf[100];
		recv(sockConn,recvBuf,100,0);//服务器从客户端接受数据
		printf("%s\n",recvBuf);
		closesocket(sockConn);//关闭socket
	}

	closesocket(sockConn);         //关闭套接字
	getchar();
	return 0;
}
②客户端的程序

<pre name="code" class="cpp">#include "stdafx.h"
#include <Winsock2.h>
#include <stdio.h>
#include <string.h>

#pragma comment(lib,"WS2_32.LIB")

//********************************************************************************************************/
//** 函数名 ** StartSock()
//**  输入  ** 无
//**  输出  ** 无
//**函数描述** 加载套接字
//********************************************************************************************************/
int SocketInit()
{
	WORD wVersionRequested;
	WSADATA wsaData;
	int err;

	wVersionRequested=MAKEWORD(2,2);
	err = WSAStartup(wVersionRequested,&wsaData); //返回0,成功,否则就是错误码

	if (err!=0)
	{
		printf("WinSock DLL版本不足要求n");
		return 0;
	}

	if (LOBYTE(wsaData.wVersion)!=2||
		HIBYTE(wsaData.wVersion)!=2)
	{
		WSACleanup();
		return 0;
	}

	return 1;
}

//********************************************************************************************************/
//** 函数名 ** main()
//**  输入  ** 无
//**  输出  ** 无
//**函数描述** 主函数
//********************************************************************************************************/
int main()
{
    //固定格式
    char recvBuf[1024];
	
	if (SOCKET_ERROR ==SocketInit())
 	{
 		return -1;
 	}
    //建立通讯socket
    SOCKET sockClient=socket(AF_INET,SOCK_STREAM,0);

    SOCKADDR_IN addrSrv;
    addrSrv.sin_addr.S_un.S_addr=inet_addr("192.168.1.100");//设定需要连接的服务器的ip地址
    addrSrv.sin_family=AF_INET;
    addrSrv.sin_port=htons(6001);//设定需要连接的服务器的端口地址
    connect(sockClient,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));//与服务器进行连接

    //接受来自老师的信息
  
	int iRevLen = 0;
    iRevLen = recv(sockClient,recvBuf,strlen(recvBuf)+1,0);
	if(0 == iRevLen)
	{
		return -1;
	}
	else if(SOCKET_ERROR == iRevLen)
	{
		printf("Recv Failed\n!");
		return -1;
	}
    printf("%s\n",recvBuf);

	char str[100];
	gets(str);
    send(sockClient,str,strlen(str)+1,0);

	closesocket(sockClient);
    WSACleanup();
	getchar();
	return -1;
}


 
 

你可能感兴趣的:(socket,网络编程,tcpip)