上次的两次面试,一位面试官认真的看了我的博客(十分感动),然后建议我好好复习下socket还有操作系统。感觉找工作好多都要求socket编程,于是我再预习复习一下。主要是当时这门课学校老师照本宣科,连代码都不讲,也很没意思,学生混老师也混。下面切入正题吧,我今天就复习这么多。
这是在WIN上创建socket,创建项目时使用win32控制台,要注意linux上是没有windows.h头文件的,所以这么写是不可以的。
#include <iostream>
#include<Windows.h>
using namespace std;
int main(int argc,char* argv[])
{
//初始化动态链接库
WSADATA ws;
WSAStartup(MAKEWORD(2, 2), &ws);//22是版本号,加载动态链接库
int sock = socket(AF_INET, SOCK_STREAM, 0);//AF_INET指明调用TCP/IP协议,SOCK_STREAM是TCP的协议(相对于UDP来讲)
cout << sock << endl;//打印句柄id,失败返回负值
//失败提示
if (sock == -1)
{
cout << "create socket failed!" << endl;
return -1;
}
closesocket(sock);//关闭连接
return 0;
}
创建TCP服务器主要是建立结构体saddr,它是sockaddr_in类的,并绑定端口,使用bind:
#include <iostream>
#include<Windows.h>
using namespace std;
int main(int argc,char* argv[])
{
//初始化动态链接库
WSADATA ws;
WSAStartup(MAKEWORD(2, 2), &ws);//22是版本号,加载动态链接库
int sock = socket(AF_INET, SOCK_STREAM, 0);//AF_INET指明调用TCP/IP协议,SOCK_STREAM是TCP的协议(相对于UDP来讲)
cout << sock << endl;//打印句柄id,失败返回负值
//失败提示
if (sock == -1)
{
cout << "create socket failed!" << endl;
return -1;
}
//测试端口号
unsigned short port = 8080;
if (argc > 1)
{
port = atoi(argv[1]);
}
//创建TCP相关的结构体
sockaddr_in saddr;
saddr.sin_family = AF_INET;//使用TCP
saddr.sin_port = htons(port);//本地字节序转网络字节序
//X86架构是小端的而网络字节流是大端的,
//Linux不一定,小型linux使用的也是和网路字节序一样的话转换也只是一个空的宏,
//这时候会可有可无,但考虑兼容性要求建议加上
saddr.sin_addr.s_addr = htonl(0);//这里可以指定网卡,0是任意的意思
if (bind(sock, (sockaddr*)&saddr, sizeof(saddr)) != 0)//绑定端口号到上面创建的socket,并判断是否成功
{
cout << "bind port " << port << " failed!" << endl;
return -2;
}
else
{
cout<< "bind port " << port << " success!" << endl;
}
closesocket(sock);//关闭连接
return 0;
}
可以看到,系统资源足够是不会失败的:
接下来是监听listen和建立连接accept。我使用了telnet来测试,IP就是本机ip,可以使用ipconfig命令查看;端口号是之前设定的8080端口。代码如下:
#include <iostream>
#include<Windows.h>
using namespace std;
int main(int argc,char* argv[])
{
//初始化动态链接库
WSADATA ws;
WSAStartup(MAKEWORD(2, 2), &ws);//22是版本号,加载动态链接库
int sock = socket(AF_INET, SOCK_STREAM, 0);//AF_INET指明调用TCP/IP协议,SOCK_STREAM是TCP的协议(相对于UDP来讲)
cout << sock << endl;//打印句柄id,失败返回负值
//失败提示
if (sock == -1)
{
cout << "create socket failed!" << endl;
return -1;
}
//测试端口号
unsigned short port = 8080;
if (argc > 1)
{
port = atoi(argv[1]);
}
//创建TCP相关的结构体
sockaddr_in saddr;
saddr.sin_family = AF_INET;//使用TCP
saddr.sin_port = htons(port);//本地字节序转网络字节序
//X86架构是小端的而网络字节流是大端的,
//Linux不一定,小型linux使用的也是和网路字节序一样的话转换也只是一个空的宏,
//这时候会可有可无,但考虑兼容性要求建议加上
saddr.sin_addr.s_addr = htonl(0);//这里可以指定网卡,0是任意的意思
if (bind(sock, (sockaddr*)&saddr, sizeof(saddr)) != 0)//绑定端口号到上面创建的socket,并判断是否成功
{
cout << "bind port " << port << " failed!" << endl;
return -2;
}
else
{
cout<< "bind port " << port << " success!" << endl;
}
listen(sock, 10);//监听,接受连接;10是列表大小,套接字接收队列的最大大小
//accept每调用一次队列就会减少一个
int client = accept(sock, 0, 0);//不需要连接信息
cout << client << endl;
closesocket(sock);//关闭连接
return 0;
}
这是测试案例:
telnet 192.168.1.110 8080
返回结果如下:
如果要取得连接者的信息的话,得在accept中传入相应的信息:
#include <iostream>
#include<ws2tcpip.h>
#include<Windows.h>
using namespace std;
int main(int argc, char* argv[])
{
//初始化动态链接库
WSADATA ws;
WSAStartup(MAKEWORD(2, 2), &ws);//22是版本号,加载动态链接库
int sock = socket(AF_INET, SOCK_STREAM, 0);//AF_INET指明调用TCP/IP协议,SOCK_STREAM是TCP的协议(相对于UDP来讲)
cout << sock << endl;//打印句柄id,失败返回负值
//失败提示
if (sock == -1)
{
cout << "create socket failed!" << endl;
return -1;
}
//测试端口号
unsigned short port = 8080;
if (argc > 1)
{
port = atoi(argv[1]);
}
//创建TCP相关的结构体
sockaddr_in saddr;
saddr.sin_family = AF_INET;//使用TCP
saddr.sin_port = htons(port);//本地字节序转网络字节序
//X86架构是小端的而网络字节流是大端的,
//Linux不一定,小型linux使用的也是和网路字节序一样的话转换也只是一个空的宏,
//这时候会可有可无,但考虑兼容性要求建议加上
saddr.sin_addr.s_addr = htonl(0);//这里可以指定网卡,0是任意的意思
if (bind(sock, (sockaddr*)&saddr, sizeof(saddr)) != 0)//绑定端口号到上面创建的socket,并判断是否成功
{
cout << "bind port " << port << " failed!" << endl;
return -2;
}
else
{
cout << "bind port " << port << " success!" << endl;
}
listen(sock, 10);//监听,接受连接;10是列表大小,套接字接收队列的最大大小
//accept每调用一次队列就会减少一个
sockaddr_in caddr;
socklen_t len = sizeof(caddr);
int client = accept(sock, (sockaddr*)&caddr, &len);//取信息
cout << client << endl;
char* ip = inet_ntoa(caddr.sin_addr);
unsigned short cport = ntohs(caddr.sin_port);//网络字节序转本地字节序
cout << "client ip is " << ip << " port is " << cport << endl;
closesocket(sock);//关闭连接
return 0;
}
END