getservbyname()
将一些服务名转换为熟知的端口号
如HTTP:80
gethostbyname()
域名解析将域名转换称为ip
getprotobyname()
协议号的解析
对于dev c++
分开的代码编译不了。
https://blog.csdn.net/qq_31869107/article/details/81234785
设计一个connectsock过程封装底层代码
//consock.cpp
#include
#include
#include
#include
#ifdef INADDR_NONE
#define INADDR_NONE 0xffffffff
#endif //写不写都一样winsock.h里有完成的。
void errexit(const char *, ...); //异常退出函数
SOCKET connectsock(const char * host, const char * service,
const char * transport)
{
struct hostent * phe; //域名解析将域名解析成ip的返回地址
struct servent * pse; //常用端口号函数返回值 存放
struct protoent * ppe; //协议号
struct sockaddr_in sin; //目标地址
int s, type; //描述符(windows 叫句柄)和传输类型(UDP/TCP)
memset(&sin, 0, sizeof(sin)); //清0
sin.sin_family = AF_INET; //IPv4
if (pse = getservbyname(service, transport)) //获取服务端口号
sin.sin_port = pse->s_port;
else if((sin.sin_port = htons((u_short)atoi(service))) == 0) //如果是端口,htons转化成网络字节
errexit("can't get %s service entry\n", service); //都不是报错退出
if (phe = gethostbyname(host)) //获取域名ip
memcpy(&sin.sin_addr, phe->h_addr, phe->h_length); //复制phe的lengh长度到sin
else if ((sin.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE) //如果是ip地址 inet_addr十进制的数转化为二进制的数
errexit("can't get %s host entry\n", host);
if ((ppe = getprotobyname(transport)) == 0) //协议号
errexit("can't get %s protocol entry\n", transport);
if (strcmp(transport, "udp") == 0)
type = SOCK_DGRAM;
else
type = SOCK_STREAM;
s = socket(PF_INET, type, ppe->p_proto); //创建套接字
if (s == INVALID_SOCKET)
errexit("can't create socket:%d\n", GetLastError());
if (connect(s, (SOCKADDR *)&sin, sizeof(sin)) == SOCKET_ERROR) //连接服务器
errexit("can't connect to %s.%s:%d\n", host, service, GetLastError());
return s;
}
connectTCP过程
//conTCP.cpp
#include
SOCKET connectsock(const char *, const char *, const char *);
SOCKET connectTCP(const char * host , const char * service)
{
return connectsock(host, service, "tcp");
}
异常处理
//errexit.cpp
#include
#include
#include
#include
void errexit(const char * format, ...)
{
va_list args;
va_start(args, format);
vfprintf(stderr, format, args);
va_end(args);
WSACleanup();
exit(1);
}
客户端主函数
//TCPdtc.cpp
#include
#include
#include
void TCPdaytime(const char *, const char *);
void errexit(const char *, ...);
SOCKET connectTCP(const char *, const char *);
#define LINELEN 128
#define WSVERS MAKEWORD(2, 0)
int main(int argc, char const *argv[])
{
const char *host = "localhost"; //目标
const char *service = "daytime"; //服务
WSADATA wsadata;
switch (argc)
{
case 1:
host = "localhost";
break;
case 3:
service = argv[2];
case 2:
host = argv[1];
break;
default:
fprintf(stderr, "usage: TCPdaytime");
exit(1);
}
if (WSAStartup(WSVERS, &wsadata) != 0) //初始化
errexit("WSASTARTUP, FAILED\n");
TCPdaytime(host, service);
WSACleanup();
return 0;
}
void TCPdaytime(const char * host, const char * service)
{
char buf[LINELEN + 1];
SOCKET s;
int cc;
s = connectTCP(host, service);
cc = recv(s, buf, LINELEN, 0);
while (cc != SOCKET_ERROR && cc > 0) //tcp是一点一点传输的过来的不是完整的包所以要循环
{
buf[cc] = '\0';
(void)fputs(buf, stdout);
cc = recv(s, buf, LINELEN, 0);
}
closesocket(s);
}
服务器端
//passsock.cpp
#include
#include
#include
void errexit(const char * , ...);
SOCKET passivesock(const char * service, const char * transport, int qlen)
{
struct servent * pse;
struct protoent * ppe;
struct sockaddr_in sin;
SOCKET s;
int type;
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
if (pse = getservbyname(service, transport))
sin.sin_port = (u_short)pse->s_port;
else if((sin.sin_port = htons((u_short)atoi(service))) == 0)
errexit("can't get %s\n", service);
if ((ppe = getprotobyname(transport)) == 0)
errexit("can't get %s", transport);
if (strcmp(transport, "udp") == 0)
type = SOCK_DGRAM;
else
type = SOCK_STREAM;
s = socket(PF_INET, type, ppe->p_proto);
if (s == INVALID_SOCKET)
errexit("can't create socket:%d\n",GetLastError());
if (bind(s, (SOCKADDR *)&sin, sizeof(sin)) == SOCKET_ERROR)
errexit("can't bind %s port, %d", service, GetLastError());
if(type == SOCK_STREAM && listen(s, qlen) == SOCKET_ERROR)
errexit("can't listen on %s port:%d", service, GetLastError());
return s;
}
//passiveTCP.cpp
#include
SOCKET passivesock(const char *, const char *, int);
SOCKET passiveTCP(const char * service, int qlen)
{
return passivesock(service, "tcp", qlen);
}
主程序
#include
#include
#include
#include
void errexit(const char *, ...);
void TCPdaytimed(SOCKET);
SOCKET passiveTCP(const char *, int);
#define QLEN 5
#define WSVERS MAKEWORD(2, 0)
void main(int argc, char *argv[])
{
struct sockaddr_in fsin;
char *service = "daytime";
SOCKET msock, ssock;
int alen;
WSADATA wsadata;
switch (argc)
{
case 1:
/* code */
break;
case 2:
service = argv[1];
default:
errexit("usage:TCPDAYTIMED\n");
}
if (WSAStartup(WSVERS, &wsadata) != 0)
errexit("failed\n");
msock = passiveTCP(service, QLEN);
while (1)
{
alen = sizeof(SOCKADDR);
ssock = accept(msock, (SOCKADDR *)&fsin, &alen);
if (ssock == INVALID_SOCKET)
errexit("accept %d", GetLastError());
if (_beginthread((void(*)(void *))TCPdaytimed, 0,
(void *)ssock) < 0)
{
errexit("_beg%s", strerror(errno));
}
}
}
void TCPdaytimed(SOCKET fd)
{
char * pts;
time_t now;
(void)time(&now);
pts = ctime(&now);
(void)send(fd, pts, strlen(pts), 0);
(void)closesocket(fd);
}
出自 : 计算机网络之网尽其用
https://www.icourse163.org/learn/HIT-154005?tid=1206679208#/learn/announce