Socket编程-----基础

Socket的概念:

Socket,即套接字,用于描述地址和端口,是一个通信链的句柄。

应用程序通过Socket像网络发出请求或者回应。


什么事客户/服务器模式:

在TCP/IP网络应用中,通信的两个进程相互作用的主要模式是客户/服务器模式,即客户端向服务器发出请求,服务器接收请求后,提供相应的服务。客户/服务器模式的建立基于以下两点:

1:建立网络的起因是网络中软硬件资源、运算能力和信息不均等,需要共享,从而造就拥有众多资源的主机提供服务,资源较少的客户请求服务这一非对等作用

2:网间进程通信完全是异步的,相互通信的进程间既不存在父子关系,又不共享内存缓冲区

因此需要一种机制为希望通信的进程间建立联系,为二者的数据交换提供同步,这就是基于客户/服务端模式的TCP/IP

(这部分内容摘自socket编程原理)


需要做什么:

客户端:建立Socket,通过端口号和地址确定目标服务器,使用Connect连接到服务器,send发送消息,等待处理,通信完成后调用CloseSocket关闭Socket

服务端:建立Socket,声明自身的端口号和地址并绑定到Socket,使用Listen打开监听,然后不断用Accept去查看是否有连接,如果有,捕获Socket,并通过Recv获取消息的内容,通信完成后调用CloseSocket关闭这个对应Accept到的Socket,如果不再需要等待任何客户端连接,那么用CloseSocket关闭掉自身的Socket

代码示例

客户端:这里创建一个CLientNet类,用于表示一个客户

  1. #pragma once   
  2.   
  3. /* 
  4. ClinetNet.h: 
  5. 用于表示一个客户的网络操作 
  6. */  
  7.   
  8. #include <stdio.h>   
  9. #include<windows.h>   
  10.   
  11. #pragma comment(lib, "Ws2_32.lib")   
  12.   
  13. class CClientNet  
  14. {  
  15. public:  
  16.     //连接上指定服务器   
  17.     int Connect(int port,const char* address);  
  18.     //发送信息   
  19.     int SendMsg(const char* msg,int len);  
  20.     //关闭   
  21.     void Close();  
  22.   
  23. private:  
  24.     SOCKET m_sock;  
  25. };  
#pragma once

/*
ClinetNet.h:
用于表示一个客户的网络操作
*/

#include <stdio.h>
#include<windows.h>

#pragma comment(lib, "Ws2_32.lib")

class CClientNet
{
public:
	//连接上指定服务器
	int Connect(int port,const char* address);
	//发送信息
	int SendMsg(const char* msg,int len);
	//关闭
	void Close();

private:
	SOCKET m_sock;
};

  1. /* 
  2. CLientNet.cpp 
  3. */  
  4. #include "ClientNet.h"   
  5.   
  6.   
  7. int CClientNet::Connect( int port,const char* address )  
  8. {  
  9.     int rlt = 0;  
  10.   
  11.     //用于记录错误信息并输出   
  12.     int iErrMsg;  
  13.     //启动WinSock   
  14.     WSAData wsaData;  
  15.     iErrMsg = WSAStartup(MAKEWORD(1,1),&wsaData);  
  16.     if (iErrMsg != NO_ERROR)  
  17.         //有错误   
  18.     {  
  19.         printf("failed with wsaStartup error : %d\n",iErrMsg);  
  20.   
  21.         rlt = 1;  
  22.         return rlt;  
  23.     }  
  24.   
  25.     //创建Socket   
  26.     m_sock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);  
  27.     if (m_sock == INVALID_SOCKET)  
  28.         //创建Socket失败   
  29.     {  
  30.         printf("socket failed with error : %d\n",WSAGetLastError());  
  31.   
  32.         rlt = 2;  
  33.         return rlt;  
  34.     }  
  35.   
  36.     //目标服务器数据   
  37.     sockaddr_in sockaddrServer;  
  38.     sockaddrServer.sin_family = AF_INET;  
  39.     sockaddrServer.sin_port = port;  
  40.     sockaddrServer.sin_addr.s_addr = inet_addr(address);  
  41.   
  42.     //连接,sock与目标服务器连接   
  43.     iErrMsg = connect(m_sock,(sockaddr*)&sockaddrServer,sizeof(sockaddrServer));  
  44.     if (iErrMsg < 0)  
  45.     {  
  46.         printf("connect failed with error : %d\n",iErrMsg);  
  47.   
  48.         rlt = 3;  
  49.         return rlt;  
  50.     }  
  51.   
  52.     return rlt;  
  53. }  
  54.   
  55.   
  56.   
  57.   
  58. int CClientNet::SendMsg(const char* msg,int len)  
  59. {  
  60.     int rlt = 0;  
  61.   
  62.     int iErrMsg = 0;  
  63.   
  64.     //发送消息,指定sock发送消息   
  65.     iErrMsg = send(m_sock,msg,len,0);  
  66.     if (iErrMsg < 0)  
  67.         //发送失败   
  68.     {  
  69.         printf("send msg failed with error : %d\n",iErrMsg);  
  70.   
  71.         rlt = 1;  
  72.         return rlt;  
  73.     }  
  74.   
  75.     return rlt;  
  76. }  
  77.   
  78. void CClientNet::Close()  
  79. {  
  80.     closesocket(m_sock);  
  81. }  
/*
CLientNet.cpp
*/
#include "ClientNet.h"


int CClientNet::Connect( int port,const char* address )
{
	int rlt = 0;

	//用于记录错误信息并输出
	int iErrMsg;
	//启动WinSock
	WSAData wsaData;
	iErrMsg = WSAStartup(MAKEWORD(1,1),&wsaData);
	if (iErrMsg != NO_ERROR)
		//有错误
	{
		printf("failed with wsaStartup error : %d\n",iErrMsg);

		rlt = 1;
		return rlt;
	}

	//创建Socket
	m_sock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
	if (m_sock == INVALID_SOCKET)
		//创建Socket失败
	{
		printf("socket failed with error : %d\n",WSAGetLastError());

		rlt = 2;
		return rlt;
	}

	//目标服务器数据
	sockaddr_in sockaddrServer;
	sockaddrServer.sin_family = AF_INET;
	sockaddrServer.sin_port = port;
	sockaddrServer.sin_addr.s_addr = inet_addr(address);

	//连接,sock与目标服务器连接
	iErrMsg = connect(m_sock,(sockaddr*)&sockaddrServer,sizeof(sockaddrServer));
	if (iErrMsg < 0)
	{
		printf("connect failed with error : %d\n",iErrMsg);

		rlt = 3;
		return rlt;
	}

	return rlt;
}




int CClientNet::SendMsg(const char* msg,int len)
{
	int rlt = 0;

	int iErrMsg = 0;

	//发送消息,指定sock发送消息
	iErrMsg = send(m_sock,msg,len,0);
	if (iErrMsg < 0)
		//发送失败
	{
		printf("send msg failed with error : %d\n",iErrMsg);

		rlt = 1;
		return rlt;
	}

	return rlt;
}

void CClientNet::Close()
{
	closesocket(m_sock);
}

  1. #include "ClientNet.h"   
  2.   
  3. void main()  
  4. {  
  5.     CClientNet client;  
  6.       
  7.     //连接到127.0.0.1(即本地),端口号为8888的服务端   
  8.     printf("Connect\n");  
  9.     client.Connect(8888,"127.0.0.1");  
  10.       
  11.     //发送消息   
  12.     printf("send msg\n");  
  13.     client.SendMsg("hello\0",sizeof("hello\0"));  
  14.       
  15.     //关闭socket   
  16.     printf("close\n");  
  17.     client.Close();  
  18.   
  19.     system("pause");  
  20. }  
#include "ClientNet.h"

void main()
{
	CClientNet client;
	
	//连接到127.0.0.1(即本地),端口号为8888的服务端
	printf("Connect\n");
	client.Connect(8888,"127.0.0.1");
	
	//发送消息
	printf("send msg\n");
	client.SendMsg("hello\0",sizeof("hello\0"));
	
	//关闭socket
	printf("close\n");
	client.Close();

	system("pause");
}


服务端代码:

  1. #pragma once   
  2.   
  3. /* 
  4. ServerNet.h 
  5. 用于表示服务端的网络操作 
  6.  
  7. */  
  8.   
  9. #include <stdio.h>   
  10. #include <winsock.h>   
  11.   
  12. #pragma comment (lib,"ws2_32.lib")   
  13.   
  14. class CServerNet  
  15. {  
  16. public:  
  17.   
  18.     //初始化服务器,返回0表示成功   
  19.     int Init(const char* address,int port);  
  20.   
  21.     //更新数据   
  22.     void Run();  
  23.   
  24.   
  25. private:  
  26.     SOCKET m_sock;  
  27. };  
#pragma once

/*
ServerNet.h
用于表示服务端的网络操作

*/

#include <stdio.h>
#include <winsock.h>

#pragma comment (lib,"ws2_32.lib")

class CServerNet
{
public:

	//初始化服务器,返回0表示成功
	int Init(const char* address,int port);

	//更新数据
	void Run();


private:
	SOCKET m_sock;
};

  1. /* 
  2. ServerNet.cpp 
  3. */  
  4. #include "ServerNet.h"   
  5.   
  6. int CServerNet::Init( const char* address,int port )  
  7. {  
  8.     int rlt = 0;  
  9.   
  10.     //用于记录错误信息,并输出   
  11.     int iErrorMsg;  
  12.   
  13.     //初始化WinSock   
  14.     WSAData wsaData;  
  15.     iErrorMsg = WSAStartup(MAKEWORD(1,1),&wsaData);  
  16.       
  17.     if (iErrorMsg != NO_ERROR)  
  18.     {  
  19.         //初始化WinSock失败   
  20.         printf("wsastartup failed with error : %d\n",iErrorMsg);  
  21.   
  22.         rlt = 1;  
  23.         return rlt;  
  24.     }  
  25.   
  26.     //创建服务端Socket   
  27.     m_sock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);  
  28.     if (m_sock == INVALID_SOCKET)  
  29.           
  30.     {  
  31.         //创建Socket异常   
  32.         printf("socket failed with error : %d\n",WSAGetLastError());  
  33.   
  34.         rlt = 2;  
  35.         return rlt;  
  36.     }  
  37.   
  38.     //声明信息   
  39.     sockaddr_in serverAddr;  
  40.     serverAddr.sin_family = AF_INET;  
  41.     serverAddr.sin_port = port;  
  42.     serverAddr.sin_addr.s_addr = inet_addr(address);  
  43.   
  44.     //绑定   
  45.     iErrorMsg = bind(m_sock,(sockaddr*)&serverAddr,sizeof(serverAddr));  
  46.     if (iErrorMsg < 0)  
  47.     {  
  48.         //绑定失败   
  49.         printf("bind failed with error : %d\n",iErrorMsg);  
  50.         rlt = 3;  
  51.         return rlt;  
  52.     }  
  53.   
  54.       
  55.   
  56.     return rlt;  
  57. }  
  58.   
  59. void CServerNet::Run()  
  60. {  
  61.     //公开连接   
  62.     listen(m_sock,5);  
  63.   
  64.     sockaddr_in tcpAddr;  
  65.     int len = sizeof(sockaddr);  
  66.     SOCKET newSocket;  
  67.     char buf[1024];  
  68.     int rval;  
  69.   
  70.     do   
  71.     {  
  72.         //接收信息   
  73.         newSocket = accept(m_sock,(sockaddr*)&tcpAddr,&len);  
  74.   
  75.           
  76.         if (newSocket == INVALID_SOCKET)  
  77.         {  
  78.             //非可用socket   
  79.   
  80.         }  
  81.         else  
  82.         {  
  83.             //新socket连接   
  84.             printf("new socket connect : %d\n",newSocket);  
  85.   
  86.   
  87.             //消息处理   
  88.             do  
  89.             {  
  90.                 printf("process\n");  
  91.                 //接收数据   
  92.                 memset(buf,0,sizeof(buf));  
  93.                 rval = recv(newSocket,buf,1024,0);  
  94.   
  95.                   
  96.                 if (rval == SOCKET_ERROR)  
  97.                     //这应该是个异常,当客户端没有调用closeSocket就直接退出游戏的时候,将会进入这里   
  98.                     printf("recv socket error\n");  
  99.   
  100.                   
  101.                   
  102.                 if (rval == 0)  
  103.                     //recv返回0表示正常退出   
  104.                     printf("ending connection");  
  105.                 else  
  106.                     //显示接收到的数据   
  107.                     printf("recv %s\n",buf);  
  108.   
  109.   
  110.             }while(rval != 0);  
  111.   
  112.             //关闭对应Accept的socket   
  113.             closesocket(newSocket);  
  114.         }  
  115.           
  116.   
  117.           
  118.     } while (1);  
  119.   
  120.     //关闭自身的Socket   
  121.     closesocket(m_sock);  
  122. }  
/*
ServerNet.cpp
*/
#include "ServerNet.h"

int CServerNet::Init( const char* address,int port )
{
	int rlt = 0;

	//用于记录错误信息,并输出
	int iErrorMsg;

	//初始化WinSock
	WSAData wsaData;
	iErrorMsg = WSAStartup(MAKEWORD(1,1),&wsaData);
	
	if (iErrorMsg != NO_ERROR)
	{
		//初始化WinSock失败
		printf("wsastartup failed with error : %d\n",iErrorMsg);

		rlt = 1;
		return rlt;
	}

	//创建服务端Socket
	m_sock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
	if (m_sock == INVALID_SOCKET)
		
	{
		//创建Socket异常
		printf("socket failed with error : %d\n",WSAGetLastError());

		rlt = 2;
		return rlt;
	}

	//声明信息
	sockaddr_in serverAddr;
	serverAddr.sin_family = AF_INET;
	serverAddr.sin_port = port;
	serverAddr.sin_addr.s_addr = inet_addr(address);

	//绑定
	iErrorMsg = bind(m_sock,(sockaddr*)&serverAddr,sizeof(serverAddr));
	if (iErrorMsg < 0)
	{
		//绑定失败
		printf("bind failed with error : %d\n",iErrorMsg);
		rlt = 3;
		return rlt;
	}

	

	return rlt;
}

void CServerNet::Run()
{
	//公开连接
	listen(m_sock,5);

	sockaddr_in tcpAddr;
	int len = sizeof(sockaddr);
	SOCKET newSocket;
	char buf[1024];
	int rval;

	do 
	{
		//接收信息
		newSocket = accept(m_sock,(sockaddr*)&tcpAddr,&len);

		
		if (newSocket == INVALID_SOCKET)
		{
			//非可用socket

		}
		else
		{
			//新socket连接
			printf("new socket connect : %d\n",newSocket);


			//消息处理
			do
			{
				printf("process\n");
				//接收数据
				memset(buf,0,sizeof(buf));
				rval = recv(newSocket,buf,1024,0);

				
				if (rval == SOCKET_ERROR)
					//这应该是个异常,当客户端没有调用closeSocket就直接退出游戏的时候,将会进入这里
					printf("recv socket error\n");

				
				
				if (rval == 0)
					//recv返回0表示正常退出
					printf("ending connection");
				else
					//显示接收到的数据
					printf("recv %s\n",buf);


			}while(rval != 0);

			//关闭对应Accept的socket
			closesocket(newSocket);
		}
		

		
	} while (1);

	//关闭自身的Socket
	closesocket(m_sock);
}


  1. #include "ServerNet.h"   
  2.   
  3. int main(int argc, char **argv)  
  4. {  
  5.     CServerNet serverNet;  
  6.     int iRlt = serverNet.Init("127.0.0.1",8888);  
  7.     if (iRlt == 0)  
  8.     {  
  9.         printf("init ok...\n");  
  10.         serverNet.Run();  
  11.     }  
  12.     else  
  13.         printf("serverNet init failed with error : %d\n",iRlt);  
  14.     system("pause");  
  15. }  
#include "ServerNet.h"

int main(int argc, char **argv)
{
	CServerNet serverNet;
	int iRlt = serverNet.Init("127.0.0.1",8888);
	if (iRlt == 0)
	{
		printf("init ok...\n");
		serverNet.Run();
	}
	else
		printf("serverNet init failed with error : %d\n",iRlt);
	system("pause");
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值