SOCKET建立步骤

C语言   粗体字公共部分  斜体字为服务器 其余为客户端

服务器客户端

#include

#include

#pragma comment(lib,"WS2_32.lib")

int main(int argc, char* argv[])

{

WSADATA wsaData;

WORD sockVersion = MAKEWORD(2,0);//指定版本号,使用WINSOCK2版本

::WSAStartup(sockVersion, &wsaData);//载入winsock的dll启动函数

第一个参数是WINSOCK版本号,第二个参数是指向WSADATA的指针

SOCKET s = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

//创建套接字基于TCP,第一个是协议域,AF_IMET决定了要用IPV4地址(32位)与端口号(16位)的组合,把ipv4地址和端口号组合赋给socket;第二个指定socket的类型;第三个指定协议,此处对应TCP传输协议,简单来说既是(使用TCP/IP协议;传输过程使用TCP;不适用其他特殊协议)

if(s == INVALID_SOCKET)

{

printf("error");

::WSACleanup();

//终止函数,清理,释放资源应用程序在完成对请求的socket库的使用后WSAClanup,

清除套接字资

函数来接触与socket库的绑定并且释放socket库所占用的系统资源

return 0;

}

sockaddr_in sin;//socket中装入地址信息

sockaddr_in servAddr;//定义套接字地址

sin.sin_family = AF_INET;//sin.family表示地址族,对于IP地址,sin_family将一直是AF_INET

servAddr.sin_family = AF_INET;//储存IP地址,INADDR_ANY就是制定地址为0.0.0.0的地址,

这个地址事实上表示不确定地址,或“所有地址”、“任意地址”

sin.sin_port = htons(8888);//端口号表示服务器监听的端口号使8888

servAddr.sin_port = htons(8888);//端口号表示客户端接受服务器8888端口号

sin.sin_addr.S_un.S_addr = INADDR_ANY;//储存地址,INADDR就是指定地址为

0.0.0.0的地址,这个地址事实上表示不确定地址,也就是所有的地址或任意地址

servAddr.sin_addr.S_un.S_addr = inet_addr("192.168.31.220");//本地IP地址,

inet_addr()将IP地址转为点分十进制的格式

//绑定socket,绑定地址及端口号

if(::bind(s, (LPSOCKADDR)&sin, sizeof(sin)) == SOCKET_ERROR)

参数一:指定与那个套接字绑定

参数二:指定地址

参数三:确定恢复多少数据

{

printf("error");

::WSACleanup();//清理释放资源

return 0;

}

//bind函数把一个地址族中的特定地址赋给socket。第一个参数是socket描述字,通过socket创建,唯一标识一个socket。bind()函数就是将这个表述字绑定一个名字。第二个参数指向要绑定给socket的协议地址。第三个参数对应的是地址的长度。

为服务器端定义的这个监听的socket指定一个地址及端口(port),这样客户端才知道待会儿要

连接哪一个地址的哪个端口,为此我们要调用bind函数

//监听socket,监听客户端的连接请求

if(::listen(s, 2) == SOCKET_ERROR)//监听客户端请求

参数一:被listen函数调用的套接字

参数二:连接数量的上限

{

printf("error");

::WSACleanup();//释放资源

return 0;

}

//连接主动完成连接过程,三次握手协议,谁调用了connet函数谁就是先发送数据的一方

if(::connect(s, (sockaddr*)&servAddr, sizeof(servAddr)) == -1)//连接服务器

参数一:指定数据发送的套接字

参数二:指定数据发送的目的地址,也就是服务端地址

{

printf("error");

::WSACleanup(); //释放资源

return 0;

}

char buff[156];//缓冲区

int nRecv = ::recv(s, buff, 156, 0);//接收数据并打印到屏幕上

//不论是客户还是服务器应用程序都用recv函数从TCP连接的另一端接收数据。

第一个参数:指定接收端套接字描述符

第二个参数:指明一个缓冲区,该缓冲区用来存放recv函数接收到的数据

第三个参数:指明buf的长度

第四个参数:一般设置0

if(nRecv > 0)

{

buff[nRecv] = '\0';

printf("接受数据:%s",buff);

}

sockaddr_in remoteAddr;

int nAddrLen = sizeof(remoteAddr);

SOCKET client;

char szText[] = "peter\n";//缓冲区数据

while(1)循环接受连接请求

{accept默认会阻塞进程,直到有一个客户建立连接后返回,他返回的是一个新

可用的套接字,这个套接字是连接套接字

/*accept服务器端使用,调用函数进入阻塞状态,等待用户连接,如果没有客户端进行连接,程序就在这个地方。

不会看到后面。如果有客户端连接,那么程序就执行一次然后继续循环到这里等待。*/

client = ::accept(s, (SOCKADDR*)&remoteAddr, &nAddrLen);

参数一:监听套接字,这个套接字用来监听一个端口,当有一个客户与服务器连接时,它使用这个端口号,而此时这个端口号正与这个套接字关联。当然客户不知道套接字这些细节,他只知道一个地址和一个端口号

参数二:这是一个结果参数,它用来接受一个返回值,这返回值指定客户端的地址。

//acc

if(client == INVALID_SOCKET)

{

printf("error");

continue;

}

printf("接受到一个连接:%s\r\n",inet_ntoa(remoteAddr.sin_addr));客户端IP

::send(client, szText, strlen(szText), 0); //发送数据,发送本地时间给客户端

//不论是客户还是服务器应用程序都用send函数来想TCP连接的另一端发送数据,

客户程序一般都用send函数向服务器发送请求,而服务器则通常用send函数

来向客户程序发送应答。

第一个参数:指定发送端套接字描述符

第二个参数指明一个存放应用程序要发送数据的缓冲区

第三个参数指明实际要发送的数据的字节数

第四个参数一般设置0

::closesocket(client);//关闭套接字,关闭连接

}

::closesocket(s);关闭套接字

::WSACleanup();

return 0;

}


2015.7.7

你可能感兴趣的:(SOCKET建立步骤)