1.什么是socket(参考:百度百科)
所谓socket通常也称作"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求。以J2SDK-1.3为例,Socket和ServerSocket类库位于java .net包中。ServerSocket用于服务器端,Socket是建立网络连接时使用的。在连接成功时,应用程序两端都会产生一个Socket实例,操作这个实例,完成所需的会话。对于一个网络连接来说,套接字是平等的,并没有差别,不因为在服务器端或在客户端而产生不同级别。不管是Socket还是ServerSocket它们的工作都是通过SocketImpl类及其子类完成的。
2.socket连接过程(参考:百度百科)
根据连接启动的方式以及本地套接字要连接的目标,套接字之间的连接过程可以分为三个步骤:服务器监听,客户端请求,连接确认。
a.服务器监听:是服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态。
b.客户端请求:是指由客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。
c.连接确认:是指当服务器端套接字监听到或者说接收到客户端套接字的连接请求,它就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,连接就建立好了。而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求.
socket连接流程图(以tcp/ip为例):(来源:http://goodcandle.cnblogs.com/archive/2005/12/10/294652.aspx)
3.简单的示例代码
a.server端
//socket初始化
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
return 0;
}
//创建socket
int nServerId = socket(AF_INET,SOCK_STREAM,0);
if(nServerId == -1)
{
return 0;
}
//调用bind函数将其与本机地址以及一个本地端口号绑定
sockaddr_in inet_addr;
inet_addr.sin_family = AF_INET; //协议类型是INET
inet_addr.sin_addr.s_addr = INADDR_ANY;//本机IP
inet_addr.sin_port = htons(8080); //指定端口号
if (bind(nServerId, (sockaddr *) & inet_addr, sizeof(inet_addr)) < 0)
{
int nErr = WSAGetLastError();
//关闭socket
closesocket(nServerId);
return 0;
}
//开始监听,最多允许128个客户端同时链接
if (listen(nServerId, 128) < 0)
{
//关闭socket
closesocket(nServerId);
return 0;
}
while(1)
{
sockaddr_in inet_addr;
int len = sizeof(inet_addr);
// accept 会阻塞进程,直到有客户端连接上来为止
SOCKET clientSocket = accept(nServerId, (sockaddr *)&inet_addr, &len);
if (clientSocket == INVALID_SOCKET)
{
return 0;
}
printf("received a connection from %s %d", inet_ntoa(inet_addr.sin_addr),clientSocket);
//发消息给客户端
send(clientSocket,"you are collected!",4096,0);
//接受来自客户端的消息
const int nBufSize = 4096;
char buf[nBufSize];
int nReciveSize = recv(clientSocket, buf, nBufSize, 0);
if (nReciveSize > 0)
{
printf("%s ", buf);
}
// 关闭socket
closesocket(clientSocket);
}
b.client端
//socket初始化 WSADATA wsaData; if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { return 0; } //创建socket int nClientId = socket(AF_INET,SOCK_STREAM,0); if(nClientId == -1) { return 0; } //获取服务器地址 hostent *host = gethostbyname("wz"); if(host==NULL) { return 0; } sockaddr_in inet_addr; memset(&inet_addr, 0, sizeof(inet_addr)); inet_addr.sin_family = AF_INET; memcpy(&inet_addr.sin_addr, host->h_addr, sizeof(inet_addr.sin_addr)); inet_addr.sin_port = htons(8080); //指定端口 //同服务端连接 if(connect(nClientId,(sockaddr*)&inet_addr,sizeof(sockaddr_in))<0) { closesocket(nClientId); return 0; } const int nBufSize = 4096; char buf[nBufSize]; //接受从服务端来的消息 int nReciveSize = recv(nClientId, buf, nBufSize, 0); if (nReciveSize <= 0) { closesocket(nClientId); return 0; } printf("%s,%d ", buf,nClientId); //发消息给服务端 if(send(nClientId,"thanks!",4096,0)<0) { return 0; }