补日报,之前因为复习考试,缺了几次日报。
完成了socket连接功能,并已经测试
1.socket套接字函数
#include
#include
int socket(int domain, int type, int protocol);
返回值:成功返回一个新的文件描述符,失败-1
对于IPv4,domain参数指定为AF_INET。对于TCP协议,type参数指定为SOCK_STREAM,表示面向流的传输协议。如果是UDP协议,则type参数指定为SOCK_DGRAM,表示面向数据报的传输协议。
2.bind函数
#include
#include
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
sockfd:socket文件描述符
addr:构造出IP地址加端口号
addrlen:sizeof(addr)长度
返回值:成功返回0,失败返回-1, 设置errno
bind()的作用是将参数sockfd和addr绑定在一起,使sockfd这个用于网络通讯的文件描述符监听addr所描述的地址和端口号。
3.listen函数
#include
int listen(int sockfd, int backlog);
sockfd:socket文件描述符
backlog:查看系统默认cat /proc/sys/net/ipv4/tcp_max_syn_backlog
4.accept函数
#include
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
sockdf:socket文件描述符
addr:传出参数,返回链接客户端地址信息,含IP地址和端口号
addrlen:传入传出参数(值-结果),传入sizeof(addr)大小,函数返回时返回真正接收到地址结构体的大小
返回值:成功返回一个新的socket文件描述符,用于和客户端通信,失败返回-1
5.connect函数
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
sockdf:socket文件描述符
addr:传入参数,指定服务器端地址信息,含IP地址和端口号
addrlen:传入参数,传入sizeof(addr)大小
返回值:成功返回0,失败返回-1,设置errno
客户端需要调用connect()连接服务器,connect和bind的参数形式一致,区别在于bind的参数是自己的地址,而connect的参数是对方的地址。
6.hostadress.h
#pragma once
#include
#include
#include
#include
class CHostAddress
{
public:
CHostAddress(void);
~CHostAddress(void);
CHostAddress(const char *ip, unsigned short port);
void SetIp(const char *ip);
const char* GetIp() const;
void SetPort(unsigned short port);
unsigned short GetPort() const;
private:
char m_ip[16];
unsigned short m_port;
};
.cpp
#include "hostadress.h"
CHostAddress::CHostAddress(void)
{
strcpy(m_ip,"0.0.0.0");
m_port = 0;
}
CHostAddress::~CHostAddress(void)
{
}
CHostAddress::CHostAddress(const char *ip, unsigned short port)
{
strncpy(m_ip, ip, 16);
m_port = port;
}
void CHostAddress::SetIp(const char *ip)
{
strncpy(m_ip, ip, 16);
}
const char* CHostAddress::GetIp() const
{
return m_ip;
}
void CHostAddress::SetPort(unsigned short port)
{
m_port = port;
}
unsigned short CHostAddress::GetPort() const
{
return m_port;
}
7.cbasesocket.h
#pragma once
#include "BaseStream.h"
class CBaseSocket
{
public:
CBaseSocket(void);
~CBaseSocket(void);
int GetSocket() const { return m_fd; }
void SetSocket(int fd);
CHostAddress GetAddress();
int Bind(CHostAddress addr);
int Close();
protected:
void Create(int sin_family, int flag, int protocl);
int m_fd;
CBaseStream *m_stream;
};
.cpp
#include "cbasesocket.h"
CBaseSocket::CBaseSocket(void)
:m_fd(0),
m_stream(NULL)
{
}
CBaseSocket::~CBaseSocket(void)
{
}
void CBaseSocket::Create(int sin_family, int flag, int protocl)
{
m_fd = socket(sin_family, flag, protocl);
if(m_fd == -1)
perror("socket error\n");
if (m_stream != NULL)
{
delete m_stream;
m_stream = NULL;
}
m_stream = new CBaseStream(m_fd);
}
void CBaseSocket::SetSocket(int fd)
{
m_fd = fd;
if (m_stream != NULL)
{
delete m_stream;
m_stream = NULL;
}
m_stream = new CBaseStream(m_fd);
}
CHostAddress CBaseSocket::GetAddress()
{
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
socklen_t addr_len = sizeof(addr);
if( getsockname(m_fd, (struct sockaddr *)&addr, &addr_len) == -1 )
perror("getsockname error\n");
CHostAddress hostaddr;
hostaddr.SetIp(inet_ntoa(addr.sin_addr));
hostaddr.SetPort(ntohs(addr.sin_port));
return hostaddr;
}
int CBaseSocket::Bind(CHostAddress hostaddr)
{
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(hostaddr.GetIp());
addr.sin_port = htons(hostaddr.GetPort());
int r = bind(m_fd, (struct sockaddr *)&addr, sizeof(addr));
if(r == -1)
perror("bind error\n");
return r;
}
int CBaseSocket::Close()
{
return close(m_fd);
}
8.TcpSocket
#pragma once
#include "cbasesocket.h"
#include "hostadress.h"
class CTcpSocket:
public CBaseSocket
{
public:
CTcpSocket(void);
~CTcpSocket(void);
void Create();
CHostAddress GetRemoteAddr() const;
void SetRemoteAddr(const CHostAddress remote_addr);
int Connect(CHostAddress addr);
int Read(char *buf, int buf_len);
int Write(char *buf, int buf_len);
protected:
CHostAddress m_remote_addr;
};
.cpp
#include "TcpSocket.h"
CTcpSocket::CTcpSocket(void)
{
}
CTcpSocket::~CTcpSocket(void)
{
}
void CTcpSocket::Create()
{
CBaseSocket::Create(AF_INET, SOCK_STREAM, 0);
}
CHostAddress CTcpSocket::GetRemoteAddr() const
{
return m_remote_addr;
}
void CTcpSocket::SetRemoteAddr(const CHostAddress remote_addr)
{
m_remote_addr.SetIp(remote_addr.GetIp());
m_remote_addr.SetPort(remote_addr.GetPort());
}
int CTcpSocket::Connect(CHostAddress hostaddr)
{
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(hostaddr.GetIp());
addr.sin_port = htons(hostaddr.GetPort());
int ret = connect(m_fd, (struct sockaddr *)&addr, sizeof(addr));
if(ret == -1)
perror("connect error\n");
else if(ret == 0)
SetRemoteAddr(hostaddr);
return ret;
}
int CTcpSocket::Read(char *buf, int buf_len)
{
return m_stream->Read(buf, buf_len);
}
int CTcpSocket::Write(char *buf, int buf_len)
{
return m_stream->Write(buf, buf_len);
}
8.连接测试函数
int CStartTest::run()
{
CGlobal glob;
glob.isTesting = true;
int clientNum = m_startHandle->m_edit_clientNum->text().toInt();
CTcpSocket tcpclient[clientNum];
int i;
for (i = 0; i < clientNum; i++)
{
tcpclient[i].Create();
tcpclient[i].Connect(CHostAddress("127.0.0.1", m_startHandle->password->text().toInt()));
glob.connectNum++;
if(glob.isTesting == false)
{
for(i = 0; i < glob.connectNum; i++)
close(tcpclient[i].GetSocket());
return 0;
}
}
return 0;
}