学习socket 编程首先得了解一下计算机网络,谢希仁的《计算机网络》写的还是不错的,通俗易懂,作者时不时的自问自答一些小问题真心的不错,有时感觉作者在与你对话,很值得初学者看
另外还有两篇博客写的也是不错的,很基础,链接:一个是http://www.blogjava.net/wxb_nudt/archive/2007/11/01/157623.html
另一个是http://www.cppblog.com/lf426/archive/2008/07/08/55641.html,这个博客是一个系列的,例子生动,很到位的解释
下边是我用C++写的基于TCP协议的socket 程序,你们可以先在自己的编译器上运行一下看一下效果,这样可以增加学习的动力
效果图:
服务端
客户端
具体操作:
用你的编译器(VC++6.0或者VS2008、2010)打开两次,也就是两个界面,一个作为客户端一个作为服务端,在同一个机子上进行通信,用同一个IP地址。分别将下边的两个程序粘贴到你的编辑区,将ip改为你自己机子上的ip,然后运行(注意先运行服务端的)
----------------------------------------------服务端----------------------------------------
#include "winsock2.h" //VC自带,不用下载
#include <iostream>
#pragma comment(lib,"WS2_32.LIB") //这一句可以避免代码移植的时候设置项目的库连接的麻烦
using namespace std;
class mserver
{
private:
SOCKET ssock,csock;//定义一个自身的socket 也就是服务端的socket ,和一个客户端的socket ,ssock用于监听,csock用于通讯
sockaddr_in saddr,caddr; //用来存放服务端地址和客户端地址
int len; //存放地址结构体的长度
char buf[1024]; //发送的信息
public:
mserver();
mserver(int port); //用来指定通信的地址、创建socket 环境、绑定地址和端口号
void beginlisten(); //准备侦听
void maccept(); //确认连接
int receive(); //接收信息
void close(); //关闭socket
};
mserver::mserver(int port)
{
saddr.sin_family=AF_INET; //目前为止只用设为这一个,表示的是连接Internet,在此以前还有个针对UNIX的
saddr.sin_port=htons(port); //指定端口号
saddr.sin_addr.s_addr=htonl(INADDR_ANY); //对于多ip的机器,不论客户端发送哪个ip都能接收的到的,当然也可以针对专门的ip
//注意这边的htonl,是将地址转换为网络字节序,和上边的htons 是有区别的,一个是转换short 型的一个是转换long 型的,用错会导致数据的丢失
ssock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); //创建socket
if(ssock==SOCKET_ERROR)
{
cout<<"socket建立失败"<<endl;
}
if(bind(ssock,(struct sockaddr*)&saddr,sizeof(saddr))==SOCKET_ERROR) //绑定服务器地址,必须进行绑定,而客户端就不需要,客户端由系统自动分配
{
cout<<"socket绑定失败"<<endl;
}
len=sizeof(caddr);
}
void mserver::beginlisten()
{
if(listen(ssock,10)==SOCKET_ERROR)
{
cout<<"侦听失败";
}
}
void mserver::maccept()
{
csock=accept(ssock,(struct sockaddr*)&caddr,&len); //当收到客户端的连接请求后,开始接收并创建面向客户端的socket ,accept 函数的返回值是SOCKET 型,即int 型
if(csock==INVALID_SOCKET)
{
cout<<"接收失败:"<<WSAGetLastError();
}
cout<<"与来自"<<inet_ntoa(caddr.sin_addr)<<"建立的连接"<<endl;
}
int mserver::receive()
{
memset(buf,0,1024);
if(recv(csock,buf,1024,0)==SOCKET_ERROR)
{
return 0;
}
cout<<"客户端信息:"<<buf<<endl;
char buf1[1024];
cin.getline(buf1,1024);
send(csock,buf1,1024,0);
return 1;
}
void mserver::close()
{
closesocket(ssock);
closesocket(csock);
}
int main()
{
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2,1),&wsaData))
{
cout<<"Winsock 初始化失败"<<endl;
WSACleanup();
return 0;
}
mserver sev(12345);
sev.beginlisten();
sev.maccept();
while(sev.receive());
sev.close();
WSACleanup();
return 0;
}
-----------------------------------------------------客户端-------------------------------------------
#include "winsock2.h"
#include <iostream>
#pragma comment(lib,"WS2_32.LIB")
using namespace std;
class mclient{
private:
SOCKET sock;
sockaddr_in saddr;
int len;
char buf[1024];
public:
mclient()
{
sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
len=sizeof(saddr);
}
bool mconnect(char* addr,int port);
void close();
void msend(char* mes);//send函数只能针对面向连接的
bool receive();
};
bool mclient::mconnect(char* addr,int port)
{
saddr.sin_family=AF_INET;
saddr.sin_port=htons(port);
saddr.sin_addr.s_addr=inet_addr(addr);
if(connect(sock,(struct sockaddr*)&saddr,len)==SOCKET_ERROR)
{
cout<<"连接失败:" <<WSAGetLastError();
return false;
}
return true;
}
void mclient::close()
{
closesocket(sock);
}
void mclient::msend(char* mes) //向服务端发送消息
{
send(sock,mes,strlen(mes),0);
}
bool mclient::receive()
{
memset(buf,0,1024);
if(recv(sock,buf,1024,0)==SOCKET_ERROR) //接收来自服务端的信息
{
return false;
} //recv函数对连接的和非连接的都可以使用
else
{
cout<<"服务端的回应:"<<buf<<endl;
return true;
}
}
int main()
{
char buf1[1024];
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2,1),&wsaData))
{
cout<<"Winsock初始化失败"<<endl;
WSACleanup();
return 0;
}
mclient person;
if(!person.mconnect("192.168.233.1",12345))
{
return 0;
}
while(cin.getline(buf1,1024))
{
if(strcmp(buf1,"back")==0)
{
break;
}
person.msend(buf1);
person.receive();
}
person.close();
WSACleanup();//退出socket环境
return 0;
}
代码的讲解已经写到注释里了,有些函数不了解的可以到我上边给的博客上查阅,毕竟这里涉及的函数不多