1. socket
#include <sys/types.h>
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
功能:創(chuàng)建一個(gè)套接字,返回一個(gè)文件描述符
參數(shù):
domain:通信域
AF_UNIX 本地通信
AF_INET IPV4網(wǎng)絡(luò)通信
AF_PACKET 底層通信
type:socket的類(lèi)型
SOCK_STREAM 流式套接字 tcp
SOCK_DGRAM 數(shù)據(jù)報(bào)套接字 UDP
SOCK_RAW 底層通信
protocol:協(xié)議,一般為0
返回值:
成功:文件描述符
失?。?1
例子:
int sockfd;
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("fail to socket");
//return -1;
exit(1);
}
2. bind
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
功能:將套接字與網(wǎng)絡(luò)信息結(jié)構(gòu)體綁定
參數(shù):
sockfd:文件描述符,socket的返回值
addr:網(wǎng)絡(luò)信息結(jié)構(gòu)體
通用的(一般不用):
struct sockaddr {
sa_family_t sa_family; 2個(gè)字節(jié)
char sa_data[14]; 14個(gè)字節(jié)
}
一般使用:sockaddr_in
#include <netinet/in.h>
struct sockaddr_in
{
__SOCKADDR_COMMON (sin_); 協(xié)議族 AF_INET 2字節(jié)
in_port_t sin_port; 端口號(hào) 2個(gè)字節(jié)
struct in_addr sin_addr; IP地址 4個(gè)字節(jié)
這個(gè)沒(méi)有用,為了保證與sockaddr大小一致
unsigned char sin_zero[sizeof (struct sockaddr) -
__SOCKADDR_COMMON_SIZE -
sizeof (in_port_t) -
sizeof (struct in_addr)];
};
addrlen:addr的大小
返回值:
成功:0
失?。?1
例子:
struct sockaddr_in serveraddr;
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(9999);
serveraddr.sin_addr.s_addr = inet_addr("192.168.1.23");
if(bind(sockfd, (struct sockaddr *)&serveraddr, sizeof(struct sockaddr_in)) < 0)
{
perror("fail to bind");
exit(1);
}
3. listen
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int listen(int sockfd, int backlog);
功能:將套接字設(shè)置為監(jiān)聽(tīng)模式
參數(shù):
sockfd:文件描述符,socket的返回值
backlog:允許同時(shí)響應(yīng)連接的客戶端的個(gè)數(shù)
一般設(shè)置為5 10
返回值:
成功:0
失敗:-1
例子:
if(listen(sockfd, 5) < 0)
{
perror("fail to listen");
exit(1);
}
4. accept
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
功能:阻塞等待客戶端的連接請(qǐng)求
參數(shù):
sockfd:文件描述符,socket的返回值
addr:網(wǎng)絡(luò)信息結(jié)構(gòu)體(自動(dòng)填充的客戶端的網(wǎng)絡(luò)信息結(jié)構(gòu)體)
addrlen:addr的大小
返回值:
成功:返回新的文件描述符(此文件描述符用于通信)
失敗:-1
例子:
int acceptfd;
struct sockaddr_in clientaddr;
socklen_t addlen = sizeof(clientaddr);
if((acceptfd = accept(sockfd, (struct sockaddr *)&clientaddr, &addlen)) < 0)
{
perror("fail to accept");
exit(1);
}
5. connect
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
功能:發(fā)送客戶端的連接請(qǐng)求
參數(shù):
sockfd:文件描述符,socket的返回值
addr:服務(wù)器網(wǎng)絡(luò)信息結(jié)構(gòu)體
addrlen:addr的大小
返回值:
成功:0
失?。?1
6. send
#include <sys/types.h>
#include <sys/socket.h>
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
功能:發(fā)送數(shù)據(jù)
參數(shù):
sockfd:文件描述符
服務(wù)器端:accept的返回值
客戶端:socket的返回值
buf:發(fā)送的數(shù)據(jù)
len:buf 的長(zhǎng)度
flags:標(biāo)志位
0 阻塞
MSG_DONTWAIT 非阻塞
返回值:
成功:發(fā)送的數(shù)據(jù)的長(zhǎng)度
失?。?1
7. recv
#include <sys/types.h>
#include <sys/socket.h>
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
功能:接收數(shù)據(jù)
參數(shù):
sockfd:文件描述符
服務(wù)器端:accept的返回值
客戶端:socket的返回值
buf:接收的數(shù)據(jù)
len:buf 的長(zhǎng)度
flags:標(biāo)志位
0 阻塞
MSG_DONTWAIT 非阻塞
返回值:
成功:接收的數(shù)據(jù)的長(zhǎng)度
0:表示對(duì)方異常退出時(shí),此時(shí)recv返回0
失?。?1
TCP網(wǎng)絡(luò)編程
#include <stdio.h> //printf
#include <arpa/inet.h> //inet_addr htons
#include <sys/types.h>
#include <sys/socket.h> //scoket bind listen accept connect
#include <netinet/in.h> //sockaddr_in
#include <stdlib.h> //exit
#include <unistd.h> //close
#include <string.h>
#define N 128
#define errlog(errmsg) do{perror(errmsg);\
printf("%s-->%s-->%d\n", __FILE__, __func__, __LINE__);\
exit(1);\
}while(0)
服務(wù)器端
int main(int argc, const char *argv[])
{
int sockfd, acceptfd;
struct sockaddr_in serveraddr, clientaddr;
socklen_t addrlen = sizeof(serveraddr);
char buf[N] = {};
if(argc < 3)
{
printf("the argument is too less\n");
exit(1);
}
//第一步:創(chuàng)建套接字
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
errlog("fail to socket");
}
//第二步:填充服務(wù)器網(wǎng)絡(luò)信息結(jié)構(gòu)體
//inet_addr:將點(diǎn)分十進(jìn)制IP地址轉(zhuǎn)化為網(wǎng)絡(luò)字節(jié)序的整型數(shù)據(jù)
//htons:將主機(jī)字節(jié)序轉(zhuǎn)化為網(wǎng)絡(luò)字節(jié)序
//atoi:將數(shù)字型字符串轉(zhuǎn)化為整型數(shù)據(jù)
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
serveraddr.sin_port = htons(atoi(argv[2]));
//第三步:將套接字域網(wǎng)絡(luò)信息結(jié)構(gòu)體綁定
if(bind(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0)
{
errlog("fail to bind");
}
//第四步:將套接字設(shè)置為監(jiān)聽(tīng)狀態(tài)
if(listen(sockfd, 5) < 0)
{
errlog("fail to listen");
}
//第五步:阻塞等待客戶端的連接請(qǐng)求
if((acceptfd = accept(sockfd, (struct sockaddr *)&clientaddr, &addrlen)) < 0)
{
errlog("fail to accept");
}
//接收數(shù)據(jù),并打印
recv(acceptfd, buf, N, 0);
printf("buf : %s\n", buf);
close(acceptfd);
close(sockfd);
return 0;
}
客戶端
int main(int argc, const char *argv[])
{
int sockfd;
struct sockaddr_in serveraddr;
socklen_t addrlen = sizeof(serveraddr);
char buf[N] = {};
if(argc < 3)
{
printf("the argument is too less\n");
exit(1);
}
//第一步:創(chuàng)建套接字
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
errlog("fail to socket");
}
//第二步:填充服務(wù)器網(wǎng)絡(luò)信息結(jié)構(gòu)體
//inet_addr:將點(diǎn)分十進(jìn)制IP地址轉(zhuǎn)化為網(wǎng)絡(luò)字節(jié)序的整型數(shù)據(jù)
//htons:將主機(jī)字節(jié)序轉(zhuǎn)化為網(wǎng)絡(luò)字節(jié)序
//atoi:將數(shù)字型字符串轉(zhuǎn)化為整型數(shù)據(jù)
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
serveraddr.sin_port = htons(atoi(argv[2]));
//第三步:向服務(wù)器端發(fā)送連接請(qǐng)求
if(connect(sockfd, (struct sockaddr *)&serveraddr, addrlen) < 0)
{
errlog("fail to connect");
}
//從終端輸入,發(fā)送數(shù)據(jù)
fgets(buf, N, stdin);
buf[strlen(buf) - 1] = '\0';
if(send(sockfd, buf, N, 0) < 0)
{
errlog("fail to send");
}
close(sockfd);
return 0;
}