C/C++ socket套接字(Windows)怎么用?想了解一下。
举报
C/C++ socket套接字(Windows)怎么用
举报
早年 VC6 收录的笔记,不知现在还是否可用,可参考参考 ...
服务端:
#include <stdio.h>
#include <Winsock2.h>
#include <iostream>
using namespace std;
#pragma comment(lib, "ws2_32.lib")
#pragma warning ( disable : 4996 )
void main()
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
// 高字节-副版本,低字节-主板本
wVersionRequested = MAKEWORD( 1, 1 );
// 初始化 Winsock 服务,必须第一个调用
// 第一个参数指明程序请求使用的Socket版本
// 将某个版本填充进 wasDate 结构对象
err = WSAStartup( wVersionRequested, &wsaData ); // 函数成功则返回 0
if ( err != 0 )
return;
if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 )
{
WSACleanup();
return;
}
// AF_INET 指定:TCP、UDP 协议传输
// SOCK_STREAM 指定用 AF_INET 中的 TCP 传输
SOCKET sockSrv = socket( AF_INET, SOCK_STREAM, 0 );
/***** 填充结构,用在 bind、connect、recvfrom、sendto() 函数 *****/
SOCKADDR_IN addrSrv;
// 服务器监听 6000 端口,客户端那里就新建一个 socket 与 6000 值的端口进行链接,该服务器就会 accept() 到那个链接了
// 貌似也可以写成 addrSrv.sin_addr.S_addr = inet_addr( "127.0.0.1" ); 之类的
// 服务端不用指定自己的 ip 的,直接设置 any 任何ip 即可。 这样在客户端使用服务端的 公网 ip socket 即可
addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY); // 使用自己或其它的 ip 地址,htons() 将数字转换成网络数据格式
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons(6000); // 端口号
// sockaddr_in和sockaddr是并列的结构,指向sockaddr_in的结构体的指针也可以指向 sockaddr的结构体
// 将套接字与端口之类的绑定,才能监听端口
bind( sockSrv, (SOCKADDR*)&addrSrv ,sizeof(SOCKADDR) );
// 使套接字处于监听状态
listen( sockSrv, 5 ); // 最多允许 5 台主机链接
SOCKADDR_IN addrClient;
int len = sizeof(SOCKADDR);
while(1)
{
// 等待一个主机的接入,并填充 addrClient 结构,储存了客户机的信息
SOCKET sockConn = accept( sockSrv, (SOCKADDR*)&addrClient, &len );
char sendBuf[50];
sprintf( sendBuf, "Welcome %s to here!", inet_ntoa(addrClient.sin_addr) );
// 6000 只是用来确定该服务器与客户端需要链接!!
cout << addrClient.sin_port << endl; // 输出的不是客户端设置的 6000,而是一个系统分配给它的一个可用端口!1
cout << "我在等客户机发送消息过来" << endl;
// 阻塞式接受消息!!客户端必须有消息发送过来、或者客户端 退出。才会继续!!!!
char recvBuf[50];
recv( sockConn, recvBuf, 50, 0 ); // 一直停着监视 sockConn 链接,客户端有消息过来、或关闭之类的动作才会继续
// 给客户机发送消息
send( sockConn, sendBuf, strlen(sendBuf) + 1, 0 );
printf( "%s\n", recvBuf );
closesocket( sockConn );
}
}
客户端:
#include <stdio.h>
#include <Winsock2.h>
#include <iostream>
using namespace std;
#pragma comment(lib, "ws2_32.lib")
void main()
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 1, 1 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 )
return;
if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 )
{
WSACleanup( );
return;
}
// sockClient 不是代表主机,而是代表这个主机与服务器之间的链接线路。
// 向该链接 sockClient 发送消息就是发送给服务器
// 与服务器的 SOCKET socket = accept( socketSer... ) 相对应,但不相等;
// 同理,服务器向 socket 发送消息也就是发送给客户端了
SOCKET sockClient = socket( AF_INET, SOCK_STREAM, 0 );
SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr = inet_addr( "127.0.10.1" );
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons( 6000 ); // 监听端口,需与服务器的相同
// 将主机与服务器链接,因为有个服务器监听的就是 6000 端口,所以此时服务器的 accept() 会返回一个 socket
connect( sockClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR) );
// 给主机的 socket 发送消息就是给服务器发送消息
send( sockClient, "hello", strlen("hello") + 1, 0 );
char recvBuf[50] = {0};
recv( sockClient, recvBuf, 50, 0 );
printf("%s\n",recvBuf);
closesocket(sockClient);
WSACleanup();
}