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类,用于表示一个客户
- #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;
- };
- /*
- 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);
- }
- #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");
- }
服务端代码:
- #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;
- };
- /*
- 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);
- }
- #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");
- }