Socket编程报告(TCP/IP协议)
1.实验目的
通过C++来实现TCP/IP协议下的Socket编程,掌握TCP协议的算法实现。
2.实验原理
客户端 建立Socket,通过端口号和地址确定目标服务器,使用connect连接到服务器,send发送消息,等待处理,通信完成后调用CloseSocket关闭Socket
服务端 建立Socket,声明自身的端口号和地址并绑定到Socket,使用Listen打开监听,然后不断用Accept去查看是否有连接,如果有,捕获Socket,并通过Recv获取消息的内容,通信完成后调用CloseSocket关闭这个对应Accept到的Socket,如果不再需要等待任何客户端连接,那么用CloseSocket关闭掉自身的Socket
3.实验代码(C++实现)
服务器端代码如下:
#pragma once
#include
#include
#pragma comment (lib,"ws2_32.lib")
class CServerNet
{
public:
//初始化服务器,返回0表示成功
int Init(const char* address,int port);
//更新数据
void Run();
private:
SOCKET m_sock;
};
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);
}
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");
}
客户端代码如下:
#pragma once
#include
#include
#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;
};
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);
}
int 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");
}
4.实验结果
5.心得体会
通过本次实验,我了解了TCP/IP协议与UDP协议的异同之处,理解了Socket在通信中的地位和作用。在调试程序过程中的查错纠错也让我对程序有了深刻的理解,虽然程序是借鉴他人的,但我通过调试之后的进一步解析阅读也掌握了其中的原理,收获颇丰。