1、关于字节排序 网际协议采用大端字节序,来传输多字节整数。 系统提供了转换的宏定义,如果主机与网际协议相同,则宏定义为空。
2、客户端 socket -> connect(阻塞,三次握手)-> rcv
3、服务器端 socket -> bind -> listen -> accept(阻塞,三次握手)-> send4、函数介绍
a..socket
1)函数原型 int socket(int family, int type, int protocol)
2)参数: family: 协议族AF_INET,IPv4协议 ... type : type 套接字类型SOCK_STREAM 字节流套接字 protocol: IPPROCO_TCP IPPROCO_UDP IPPROCO_SCTP
3)返回值 成功:返回套接字符 错误:返回INVALID_SOCKET(-1)
4)示例
#include
#include
#include
int main()
{
int socketfd;
struct sockaddr_in servaddr;
if((socketfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
return -1;
}
}
#include
#include
#include
#include
#include
int main()
{
int socketfd;
struct sockaddr_in servaddr;
if((socketfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
printf("socket error\n");
return -1;
}
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_addr.s_addr = inet_addr("192.168.0.218");
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(55000);
if(connect(socketfd, (struct sockaddr*) &servaddr, sizeof(servaddr)) < 0)
{
printf("connect error\n");
}
return 0;
}
4)示例
#include
#include
#include
#include
#include
int main()
{
int count = 0;
int listenfd, socketfd;
int nread;
struct sockaddr_in servaddr;
struct timeval timeoutval;
char readbuf[256];
printf("accept started\n");
//socket
if((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
printf("socket error\n");
return -1;
}
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(59000);
//bind
if(bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)
{
printf("bind error\n");
//return -1;
}
//listen
listen(listenfd, 5);
//accept
socketfd = accept(listenfd, NULL, NULL);
while(1)
{
printf("start receive %d...\n", count++);
memset(readbuf, sizeof(readbuf), 0);
nread = recv(socketfd, readbuf, 10, 0);
if(nread>0)
{
readbuf[10] = '\0';
printf("receiveed %s, nread = %d\n\n", readbuf, nread);
}
}
return 0;
}
/* 实现功能:通过select处理多个socket
* 监听一个端口,监听到有链接时,添加到select的w.
*/
#include "select.h"
#include
#include
#include
#include
#include
#include
typedef struct _CLIENT{
int fd;
struct sockaddr_in addr; /* client's address information */
} CLIENT;
#define MYPORT 59000
//最多处理的connect
#define BACKLOG 5
//最多处理的connect
CLIENT client[BACKLOG];
//当前的连接数
int currentClient = 0;
//数据接受 buf
#define REVLEN 10
char recvBuf[REVLEN];
//显示当前的connection
void showClient();
int main()
{
int i, ret, sinSize;
int recvLen = 0;
fd_set readfds, writefds;
int sockListen, sockSvr, sockMax;
struct timeval timeout;
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
for(i=0; i0)
{
FD_SET(client[i].fd, &readfds);
if(sockMax0 && FD_ISSET(client[i].fd, &readfds))
{
if(recvLen != REVLEN)
{
while(1)
{
//recv数据
ret = recv(client[i].fd, (char *)recvBuf+recvLen, REVLEN-recvLen, 0);
if(ret == 0)
{
client[i].fd = -1;
recvLen = 0;
break;
}
else if(ret < 0)
{
client[i].fd = -1;
recvLen = 0;
break;
}
//数据接受正常
recvLen = recvLen+ret;
if(recvLen
5) 示例
/* 实现功能:通过poll, 处理多个socket
* 监听一个端口,监听到有链接时,添加到poll.
*/
#include "select.h"
#include
#include
#include
#include
#include
#include
#include
typedef struct _CLIENT{
int fd;
struct sockaddr_in addr; /* client's address information */
} CLIENT;
#define MYPORT 59000
//最多处理的connect
#define BACKLOG 5
//当前的连接数
int currentClient = 0;
//数据接受 buf
#define REVLEN 10
char recvBuf[REVLEN];
#define OPEN_MAX 1024
int main()
{
int i, ret, sinSize;
int recvLen = 0;
fd_set readfds, writefds;
int sockListen, sockSvr, sockMax;
int timeout;
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
struct pollfd clientfd[OPEN_MAX];
//socket
if((sockListen=socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("socket error\n");
return -1;
}
bzero(&server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(MYPORT);
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
//bind
if(bind(sockListen, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0)
{
printf("bind error\n");
return -1;
}
//listen
if(listen(sockListen, 5) < 0)
{
printf("listen error\n");
return -1;
}
//clientfd 初始化
clientfd[0].fd = sockListen;
clientfd[0].events = POLLIN; //POLLRDNORM;
sockMax = 0;
for(i=1; isockMax)
sockMax = i;
}
//读取数据
for(i=1; i<=sockMax; i++)
{
if(clientfd[i].fd < 0)
continue;
if (clientfd[i].revents & (POLLIN | POLLERR))//POLLRDNORM
{
if(recvLen != REVLEN)
{
while(1)
{
//recv数据
ret = recv(clientfd[i].fd, (char *)recvBuf+recvLen, REVLEN-recvLen, 0);
if(ret == 0)
{
clientfd[i].fd = -1;
recvLen = 0;
break;
}
else if(ret < 0)
{
clientfd[i].fd = -1;
recvLen = 0;
break;
}
//数据接受正常
recvLen = recvLen+ret;
if(recvLen
/* 实现功能:通过epoll, 处理多个socket
* 监听一个端口,监听到有链接时,添加到epoll_event
*/
#include "select.h"
#include
#include
#include
#include
#include
#include
#include
#include
typedef struct _CLIENT{
int fd;
struct sockaddr_in addr; /* client's address information */
} CLIENT;
#define MYPORT 59000
//最多处理的connect
#define MAX_EVENTS 500
//当前的连接数
int currentClient = 0;
//数据接受 buf
#define REVLEN 10
char recvBuf[REVLEN];
//EPOLL相关
//epoll描述符
int epollfd;
//事件数组
struct epoll_event eventList[MAX_EVENTS];
void AcceptConn(int srvfd);
void RecvData(int fd);
int main()
{
int i, ret, sinSize;
int recvLen = 0;
fd_set readfds, writefds;
int sockListen, sockSvr, sockMax;
int timeout;
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
//socket
if((sockListen=socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("socket error\n");
return -1;
}
bzero(&server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(MYPORT);
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
//bind
if(bind(sockListen, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0)
{
printf("bind error\n");
return -1;
}
//listen
if(listen(sockListen, 5) < 0)
{
printf("listen error\n");
return -1;
}
//1. epoll 初始化
epollfd = epoll_create(MAX_EVENTS);
struct epoll_event event;
event.events = EPOLLIN|EPOLLET;
event.data.fd = sockListen;
//2. epoll_ctrl
if(epoll_ctl(epollfd, EPOLL_CTL_ADD, sockListen, &event) < 0)
{
printf("epoll add fail : fd = %d\n", sockListen);
return -1;
}
//epoll
while(1)
{
timeout=3000;
//3. epoll_wait
int ret = epoll_wait(epollfd, eventList, MAX_EVENTS, timeout);
if(ret < 0)
{
printf("epoll error\n");
break;
}
else if(ret == 0)
{
printf("timeout ...\n");
continue;
}
//直接获取了事件数量,给出了活动的流,这里是和poll区别的关键
int n = 0;
for(n=0; ndata.fd, pEvent);
}
}
}
close(epollfd);
close(sockListen);
printf("test\n");
return 0;
}
/**************************************************
函数名:AcceptConn
功能:接受客户端的链接
参数:srvfd:监听SOCKET
***************************************************/
void AcceptConn(int srvfd)
{
struct sockaddr_in sin;
socklen_t len = sizeof(struct sockaddr_in);
bzero(&sin, len);
int confd = accept(srvfd, (struct sockaddr*)&sin, &len);
if (confd < 0)
{
printf("bad accept\n");
return;
}else
{
printf("Accept Connection: %d", confd);
}
//setnonblocking(confd);
//4. epoll_wait
//将新建立的连接添加到EPOLL的监听中
struct epoll_event event;
event.data.fd = confd;
event.events = EPOLLIN|EPOLLET;
epoll_ctl(epollfd, EPOLL_CTL_ADD, confd, &event);
}
//读取数据
void RecvData(int fd)
{
int ret;
int recvLen = 0;
memset(recvBuf, 0, REVLEN);
printf("RecvData function\n");
if(recvLen != REVLEN)
{
while(1)
{
//recv数据
ret = recv(fd, (char *)recvBuf+recvLen, REVLEN-recvLen, 0);
if(ret == 0)
{
recvLen = 0;
break;
}
else if(ret < 0)
{
recvLen = 0;
break;
}
//数据接受正常
recvLen = recvLen+ret;
if(recvLen