getservbyname()
將一些服務(wù)名轉(zhuǎn)換為熟知的端口號(hào)
如HTTP:80
gethostbyname()
域名解析將域名轉(zhuǎn)換稱為ip
getprotobyname()
協(xié)議號(hào)的解析
對(duì)于dev c++
分開的代碼編譯不了。
https://blog.csdn.net/qq_31869107/article/details/81234785
設(shè)計(jì)一個(gè)connectsock過程封裝底層代碼
//consock.cpp
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock.h>
#ifdef INADDR_NONE
#define INADDR_NONE 0xffffffff
#endif //寫不寫都一樣winsock.h里有完成的。
void errexit(const char *, ...); //異常退出函數(shù)
SOCKET connectsock(const char * host, const char * service,
const char * transport)
{
struct hostent * phe; //域名解析將域名解析成ip的返回地址
struct servent * pse; //常用端口號(hào)函數(shù)返回值 存放
struct protoent * ppe; //協(xié)議號(hào)
struct sockaddr_in sin; //目標(biāo)地址
int s, type; //描述符(windows 叫句柄)和傳輸類型(UDP/TCP)
memset(&sin, 0, sizeof(sin)); //清0
sin.sin_family = AF_INET; //IPv4
if (pse = getservbyname(service, transport)) //獲取服務(wù)端口號(hào)
sin.sin_port = pse->s_port;
else if((sin.sin_port = htons((u_short)atoi(service))) == 0) //如果是端口泻拦,htons轉(zhuǎn)化成網(wǎng)絡(luò)字節(jié)
errexit("can't get %s service entry\n", service); //都不是報(bào)錯(cuò)退出
if (phe = gethostbyname(host)) //獲取域名ip
memcpy(&sin.sin_addr, phe->h_addr, phe->h_length); //復(fù)制phe的lengh長(zhǎng)度到sin
else if ((sin.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE) //如果是ip地址 inet_addr十進(jìn)制的數(shù)轉(zhuǎn)化為二進(jìn)制的數(shù)
errexit("can't get %s host entry\n", host);
if ((ppe = getprotobyname(transport)) == 0) //協(xié)議號(hào)
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); //創(chuàng)建套接字
if (s == INVALID_SOCKET)
errexit("can't create socket:%d\n", GetLastError());
if (connect(s, (SOCKADDR *)&sin, sizeof(sin)) == SOCKET_ERROR) //連接服務(wù)器
errexit("can't connect to %s.%s:%d\n", host, service, GetLastError());
return s;
}
connectTCP過程
//conTCP.cpp
#include <winsock.h>
SOCKET connectsock(const char *, const char *, const char *);
SOCKET connectTCP(const char * host , const char * service)
{
return connectsock(host, service, "tcp");
}
異常處理
//errexit.cpp
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <winsock.h>
void errexit(const char * format, ...)
{
va_list args;
va_start(args, format);
vfprintf(stderr, format, args);
va_end(args);
WSACleanup();
exit(1);
}
客戶端主函數(shù)
//TCPdtc.cpp
#include <stdlib.h>
#include <stdio.h>
#include <winsock.h>
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"; //目標(biāo)
const char *service = "daytime"; //服務(wù)
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是一點(diǎn)一點(diǎn)傳輸?shù)倪^來的不是完整的包所以要循環(huán)
{
buf[cc] = '\0';
(void)fputs(buf, stdout);
cc = recv(s, buf, LINELEN, 0);
}
closesocket(s);
}
服務(wù)器端
//passsock.cpp
#include <stdlib.h>
#include <string.h>
#include <winsock.h>
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 <winsock.h>
SOCKET passivesock(const char *, const char *, int);
SOCKET passiveTCP(const char * service, int qlen)
{
return passivesock(service, "tcp", qlen);
}
主程序
#include <stdlib.h>
#include <winsock.h>
#include <process.h>
#include <time.h>
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);
}
出自 : 計(jì)算機(jī)網(wǎng)絡(luò)之網(wǎng)盡其用
https://www.icourse163.org/learn/HIT-154005?tid=1206679208#/learn/announce