Socket C++/C编程实现
#pragma指令:设定编译器的状态或者指示编译器完成一些特定的动作
运用socket时要预处理文件:#include<winsock.h>
在codeblocks里面编译链接时会报错
undefined reference to WSAStartup等
解决方法如下:
在project------->build options------->linker setting在otherlink options中加上:-lwsock32
服务器端代码如下:
#pragma once
#include<stdio.h>
#include<winsock.h>
#pragma comment (lib,"ws2_32.lib")
class CServernet{
public:
int Init(const char* address,int port);
void Run();
private:
SOCKET m_socket;
};
int CServernet::Init(const char* address,int port){
int rlt=0;
int iErrorMsg;
WSAData wsaData;
iErrorMsg=WSAStartup(MAKEWORD(1,1),&wsaData);//启动socket服务
if(iErrorMsg!=NO_ERROR){
printf("wsastartup failed with error: %d\n",iErrorMsg);
rlt=1;
return rlt;
}
m_socket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(m_socket==INVALID_SOCKET){
printf("socket failed with error : %d\n",WSAGetLastError());
rlt=2;
return rlt;
}
sockaddr_in serverAddr;
serverAddr.sin_family=AF_INET;//协议簇;AF_INET(又称PF_INET)是IPv4 网络协议的套接字类型
serverAddr.sin_port=port;//端口号
serverAddr.sin_addr.s_addr=inet_addr(address);//sin_addr是一个联合体,可以选择用多种方式表示ip,一般用s_addr来表示
iErrorMsg=bind(m_socket,(sockaddr*)&serverAddr,sizeof(serverAddr));//绑定
if(iErrorMsg<0){
printf("bind failed with error: %d\n",iErrorMsg);
rlt=1;
return rlt;
}
return rlt;
}
void CServernet::Run(){
listen(m_socket,5);//数字表示等待连接队列的最大长度
sockaddr_in tcpAddr;
int len=sizeof(tcpAddr);
SOCKET newSocket;
char buf[1024];
int rval;
do{
newSocket=accept(m_socket,(sockaddr*)&tcpAddr,&len);
if(newSocket==INVALID_SOCKET){
}else{
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)
printf("recv socket error\n");
if(rval==0)
printf("ending connection");
else printf("recv %s\n",buf);
}while(rval!=0);
closesocket(newSocket);
}
}while(1);
closesocket(m_socket);
}
int main(int argc,char** agrv){
CServernet cservernet;
int iRlt=cservernet.Init("127.0.0.1",8888);
if(iRlt==0){
printf("...init ok\n");
cservernet.Run();
}
else {
printf("servernet init failed with error :%d\n",iRlt);
}
system("pause");
}
注释:WSAStartup,是Windows Sockets Asynchronous的启动命令
socket accept(
socket s;
socketAddr addr;//存放客户端的地址
int len;//addr区域的长度
)
返回值是一个新的套接字描述符,表示与客户端的链接。可以理解为你有俩套接字了,原来那个m_socket还在侦听原来的端口,
新的在准备发送和接受数据。
所以服务器端 首先:调用WSAStartup,是Windows Sockets Asynchronous的启动命令,启动socket服务;其次调用socket()方法创建端口;最后bind()绑定;listen()监听;accept()接受。
客户端类似,代码如下:
#pragma once
#include<stdio.h>
#include<winsock.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_socket;
};
int CClientnet::Connect(int port,const char* address){
int rlt=0;
int iErrorMsg;
WSAData wsaData;
iErrorMsg=WSAStartup(MAKEWORD(1,1),&wsaData);//启动socket服务
if(iErrorMsg!=NO_ERROR){
printf("wsastartup failed with error: %d\n",iErrorMsg);
rlt=1;
return rlt;
}
m_socket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(m_socket==INVALID_SOCKET){
printf("socket failed with error : %d\n",WSAGetLastError());
rlt=2;
return rlt;
}
sockaddr_in serverAddr;
serverAddr.sin_family=AF_INET;//协议簇;AF_INET(又称PF_INET)是IPv4 网络协议的套接字类型
serverAddr.sin_port=port;//端口号
serverAddr.sin_addr.s_addr=inet_addr(address);//sin_addr是一个联合体,可以选择用多种方式表示ip,一般用s_addr来表示
iErrorMsg=connect(m_socket,(sockaddr*)&serverAddr,sizeof(serverAddr));//连接
if(iErrorMsg<0){
printf("bind failed with error: %d\n",iErrorMsg);
rlt=3;
return rlt;
}
return rlt;
}
int CClientnet::SendMsg(const char *msg,int len){
int rlt=0;
int iErrMsg=0;
iErrMsg=send(m_socket,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_socket);
}
int main(int argc,char** agrv){
CClientnet cclientnet;
printf("Connect\n");
cclientnet.Connect(8888,"127.0.0.1");
printf("send msg\n");
cclientnet.SendMsg("hello\0",sizeof("hello\0"));
printf("close\n");
cclientnet.Close();
system("pause");
}
即为socket通信的过程。