基于TCP的编程
前提:本文基于Linux系統(tǒng)下的學(xué)習(xí)
服務(wù)器端
1 創(chuàng)建通訊端口,返回socket設(shè)備的文件描述符 sfd
socket(2)
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
功能:創(chuàng)建一個(gè)通訊端點(diǎn)
參數(shù):
domain:
AF_INET IPv4 Internet protocols ip(7)
AF_INET6 IPv6 Internet protocols ipv6(7
type:
SOCK_STREAM:有序的 可靠的 雙工的 基于連接的 字節(jié)流 tcp
SOCK_DGRAM: 基于數(shù)據(jù)包的 不可靠的 不需要連接的 udp
protocol:0
返回值:
成功 返回一個(gè)新的文件描述符
錯(cuò)誤 -1 errno被設(shè)置
2 將sfd和服務(wù)器的地址和端口綁定
bind(2)
int bind(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);
功能:給一個(gè)socket綁定一個(gè)名字
參數(shù):
sockfd:指定socket,有了地址家族,但沒有具體的地址
addr: 指定具體的地址,根據(jù)地址家族采用具體的地址格式
addrlen:是addr所屬結(jié)構(gòu)體的字節(jié)數(shù)
返回值:
成功 0
錯(cuò)誤 -1 errno被設(shè)置
socklen_t
struct sockaddr{
sa_family_t sa_family;
char sa_data[14];
}
ipv4 ipv6
3 將sfd設(shè)置為被動(dòng)連接模式,監(jiān)聽客戶端連接的到來.連接到來的時(shí)候,將連接放入一個(gè)未決連接隊(duì)列中.listen(2)
int listen(int sockfd, int backlog);
功能:在指定的socket上監(jiān)聽連接
參數(shù):
sockfd:指定要被監(jiān)聽的socket,必須是基于TCP的.
backlog:指定了未決連接隊(duì)列的最大值
返回值:
成功 0
錯(cuò)誤 -1 errno被設(shè)置
while(1){
4 從未決連接隊(duì)列中取出一個(gè)連接進(jìn)行處理,返回一個(gè)和客戶端連接 的文件描述符cfd.阻塞 accept(2)
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
功能:從未決連接隊(duì)列中獲取第一個(gè)未決連接請(qǐng)求,創(chuàng)建一個(gè)連接socket.返回一個(gè)文件描述符cfd,使用這個(gè)cfd和客戶端傳輸數(shù)據(jù)
參數(shù):
sockfd:指定了在這個(gè)socket上獲取第一個(gè)未決連接
addr:addr指定的地址空間里填充了客戶端的地址.具體的格式取決于地址家族.如果為NULL,addrlen也被設(shè)置為NULL.
addrlen:指定了addr指向空間的大小
返回值:
錯(cuò)誤 -1 errno被設(shè)置
成功 返回一個(gè)非負(fù)的文件描述符.處理的未決連接的的文件描述符
5 使用cfd讀取客戶端的請(qǐng)求信息 read(2)
6 處理客戶端的請(qǐng)求信息
7 將處理結(jié)果回送給客戶端 write(2)
8 關(guān)閉cfd close(2)
}
?
客戶端
1 創(chuàng)建一個(gè)通訊端點(diǎn).socket設(shè)備,返回該設(shè)備的文件描述符sfd
socket(2)
2 使用sfd連接到服務(wù)器.connect(2)
int connect(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);
功能:在socket上發(fā)起一個(gè)連接
參數(shù):
sockfd:指定socket,在這個(gè)socket上發(fā)起一個(gè)連接請(qǐng)求
addr:指定了目標(biāo)的地址.具體的格式取決于socket的地址家族
addlen:指定了addr的大小
返回值:
成功 0
錯(cuò)誤 -1 errno被設(shè)置
3 向服務(wù)器發(fā)送信息
4 等待獲取服務(wù)器的處理信息
5 將獲取到的信息處理
6 告知服務(wù)器,關(guān)閉客戶端的連接. close(2)
?
補(bǔ)充:
struct sockaddr 通用地址家族
{
sa_family_t sa_family;
char sa_data[14];
};
ipv4 地址家族
struct sockaddr_in {
sa_family_t sin_family; /*address family: AF_INET */
in_port_t sin_port; /*port in network byte order */
struct in_addr sin_addr; /* internet address */
};
/* Internet address. */
struct in_addr {
uint32_t s_addr;/*address in network byte order */
};
uint32_t ====== unsigned int
in_port_t======uint16_t======unsigned short int
端口需要網(wǎng)絡(luò)字節(jié)序 大端
主機(jī)字節(jié)序 可能是大端,也可能是小端.
主機(jī)字節(jié)序=======>網(wǎng)絡(luò)字節(jié)序
#include <arpa/inet.h>
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);
ip地址 192.168.1.4 點(diǎn)分十進(jìn)制的格式 字符串 text
uint32_t binary
text<----->binary
inet_pton(3)
#include <arpa/inet.h>
int inet_pton(int af, const char *src, void *dst);
功能:text---->binary ipv4|ipv6
參數(shù):
af:
AF_INET: ipv4 sin_addr
AF_INET6:ipv6
src:字符串格式的ip地址
dst:存放轉(zhuǎn)換結(jié)果的首地址
返回值:
成功 1
src 無效 0
af 無效 -1 errno被設(shè)置
#include <arpa/inet.h>
const char *inet_ntop(int af, const void *src,
char *dst, socklen_t size);
功能:binary----->text
參數(shù):
af:
AF_INET: ipv4
AF_INET6:ipv6
src: binary格式的地址
dst: 存放轉(zhuǎn)換結(jié)果的地址
size: 指定了dst可用空間的字節(jié)數(shù)
返回值:
錯(cuò)誤 NULL errno被設(shè)置
成功 dst指向的地址
INADDR_ANY 代表本地的所有接口,所有的ip地址.
ipv6 地址家族
轉(zhuǎn)載于:https://www.cnblogs.com/qiuyuwutong/p/9350081.html
總結(jié)
- 上一篇: python_面向对象
- 下一篇: HDU 6304 Chiaki Sequ