Socket编程-----基础
2015-06-04 09:10
387 查看
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类,用于表示一个客户
[cpp]
view plaincopyprint?
#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; };
[cpp]
view plaincopyprint?
/* 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); }
[cpp]
view plaincopyprint?
#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");
}
服务端代码:
[cpp]
view plaincopyprint?
#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; };
[cpp]
view plaincopyprint?
/*
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);
}
[cpp]
view plaincopyprint?
#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"); }
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类,用于表示一个客户
[cpp]
view plaincopyprint?
#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; };
#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; };
[cpp]
view plaincopyprint?
/* 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); }
/* 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); }
[cpp]
view plaincopyprint?
#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");
}
#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"); }
服务端代码:
[cpp]
view plaincopyprint?
#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; };
#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; };
[cpp]
view plaincopyprint?
/*
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);
}
/* 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); }
[cpp]
view plaincopyprint?
#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"); }
#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"); }
相关文章推荐
- Python爬虫入门一之综述
- Java用法总结
- django 自带过滤器
- MyBatis3.1.1+Spring3.1.1的增、删、查、改以及分页和事务管理
- Spring MVC @RequestParam 如何获取前台的数组类型
- C#获取邮件客户端保存的邮箱密码
- Lua5.1中数学库
- Java 中Comparable和Comparator区别比较
- ZendStudio的常用设置
- 在线OJ读取文件防止出错的代码
- Eclipse 一直提示 loading descriptor for 解决
- JAVA学习第三十三课(经常使用对象API) —迭代器
- C语言简介
- [c++]基类对象作为函数参数(赋值兼容规则)
- 利用NuSoap开发WebService(PHP)
- Spring Security 2.0.5 学习笔记(一) - URL级别权限控制
- Qt tableWidget 空单元格 获取选中行行号
- output存储一列
- Java引用外包
- Java路上,必看书籍