LINUX TCP编程

相关结构体:

           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 */

           };

 sin_family is always set to AF_INET.  This is required;

服务器端流程

1.创建socket

2.绑定socket到端口

3.进入监听状态

4.等待客户端到来

5.和客户端通信,进行网络任务

6.断开连接

1.创建socket

#include <sys/types.h> 

#include <sys/socket.h>

int socket(int domain, int type, int protocol);

domain:通讯使用的协议簇,一般为AF_INET(IPV4)或AF_INET6(IPV6)

type:套接字类型,一般为SOCK_STREAMTCP连接)或SOCK_DGRAMUDP连接)

protocol:使用的协议,一般来说确定的协议簇只使用一种协议,所以此值一般是0.

返回0表示成功,-1表示失败,具体的错误代码在errno里面。

例:

int server_sockfd=socket(AF_INET,SOCK_STREAM,0);

if (server_sockfd == -1){

//处理错误

return -1;

}

2.绑定端口:

#include <sys/types.h>

#include <sys/socket.h>

int bind(int sockfd, const struct sockaddr *addr,

                socklen_t addrlen);

sockfd:服务端套接字句柄

addr:其实现在都使用结构体sockaddr_in代替sockaddr了,这个结构体填装了服务器要绑定的端口号,接受的IP范围,使用的协议信息。

addrlen:结构体的大小。

返回0表示成功,-1表示失败,具体的错误代码在errno里面。

例:

struct sockaddr_in server_addr;

memset(&server_addr,0,sizeof(server_addr));

server_addr.sin_family=AF_INET;

server_addr.sin_addr.s_addr=htonl(INADDR_ANY);

server_addr.sin_port=htons(SOCKET_PORT);

if(bind(server_sockfd,(struct sockaddr*)&server_addr,sizeof(server_addr)) == -1){

//处理错误

return -1;

}

3.监听:

#include <sys/types.h>

#include <sys/socket.h>

int listen(int sockfd, int backlog);

sockfd:服务端套接字句柄。

backlog:当连接到来时,排队的最大数量。

返回0表示成功,-1表示失败,具体的错误代码在errno里面。

例:

if(listen(g_server_sockfd,1) == -1){

//处理错误

return -1;

}

4.等待客户端:

#include <sys/types.h>

#include <sys/socket.h>

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

sockfd:服务端套接字句柄。

addr:客户端信息,一般是sockaddr_in结构体。

addrlen:客户端信息长度。

返回一个客户端socket句柄表示成功,-1表示失败,具体的错误代码在errno里面。

例:

int client_sockfd=-1;

struct sockaddr_in client_addr;

if((client_sockfd=accept(g_server_sockfd,(struct sockaddr*)&client_addr,&addr_len))== -1) //处理错误

    break;

}

5.通信:

接收消息:

#include <sys/types.h>

#include <sys/socket.h>

ssize_t recv(int sockfd, void *buf, size_t len, int flags);

ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,

                        struct sockaddr *src_addr, socklen_t *addrlen);

ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);

其中recv一般只用于TCP连接。

返回0表示对方关闭了连接,返回-1表示有错误发生,正常时返回接收到的数据大小。

这个函数默认是阻塞的,可以改变socket的属性来设置非阻塞或超时时间。

例:

char data_buffer[256];

while((data_len=recv(client_sockfd,data_buffer,256,0))>0){

//处理数据 

}

发送消息:

#include <sys/types.h>

#include <sys/socket.h>

ssize_t send(int sockfd, const void *buf, size_t len, int flags);

ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,

                      const struct sockaddr *dest_addr, socklen_t addrlen);

ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);

跟接收消息差不多。

6.断开连接:

#include <unistd.h>

int close(int fd);

或者:

#include <sys/socket.h>

int shutdown(int sockfd, int how);

howSHUT_RDSHUT_WRSHUT_RDWR

客户端流程

1.创建socket

和服务端一样。

2.连接服务器:

#include <sys/types.h>

#include <sys/socket.h>

int connect(int sockfd, const struct sockaddr *addr,

                   socklen_t addrlen);

sockfd:客户端套接字句柄。

addr:填充了服务器的地址和端口号,协议等信息。

返回0表示成功,-1表示失败,具体的错误代码在errno里面。

3.通信:

和服务端一样。

4.关闭:

和服务端一样。

你可能感兴趣的:(LINUX TCP编程)