linux 网络编程中结构体和使用分析

一、TCP 服务端的编程

1. int socket(int domain,int type ,int protocol)

domain:是说我们网络程序采用的通讯协议族,一般我们填AF_INET

type: 我们程序采用的通讯协议:SOCK_STREAM是TCP, SOCK_DGRAM是UDP,及数据报

protocol:因为我们使用了type,这里填0就可以了

2.int bind(int sockfd,struct sockaddr *my_addr,int addrlen)

sockfd:是由socket调用返回的文件描述符

struct sockaddr{

unsigned short as_family;

char sa_data[14];

};

不过由于系统的兼容性,我们一般不用这个,而用另外一个结构体(struct sockaddr_in)来代替。

struct sockaddr_in{

unsigned short sin_family;

unsigned short int sin_port;

struct in_addr sin_addr;

unsigned char sin_zero[8];

};

struct in_addr{

in_addr_t s_addr; //IPV4地址

};

sin_family一般为AF_INET,sin_addr.s_addr设置为INADDR_ANY,表示可以和任何计算机通信,sin_port是我们要监听的端口。成功返回0

addrlen表示sockaddr结构的长度

bind(sockfd,(struct sockaddr*)&my_addr,sizeof(struct sockaddr))

3.int listen(int sockfd,int backlog)

sockfd,是bind后的sockfd

backlog:设置请求排队的最大长度,支持多少个客户同时连接

4.int accept (int sockfd,struct sockaddr *addr,int *addrlen)

sockfd: 是listen后的文件描述符

struct sockaddr和addrlen是调用此函数中,把客户端的信息填充进去,这样我们就知道是哪个客户端在连接我们。

返回的自然是跟客户端通信的套接字了。newsock

5.收int recv(int sockfd,void*buf,int len,unsigned int flags)

flags一般为0

6.int send(int sockfd,const void*msg,int len,int flags)

flags一般为0

二、TCP客户端编程

1.sockfd= socket(AF_INET,SOCK_STREAM,0)

2.填充将要连接的服务端的地址信息

struct sockaddr_in their_addr;

their_addr.sin_family=AF_INET;

their_addr.sin_port=htons(2323); //对方使用2323进行通信

inet_aton("192.168.40.44",&their_addr.sin_addr);  //int inet_aton(const char*string,struct in_addr* addr);

3.建立连接

connect(sockfd,(struct sockaddr*)&their_addr,sizeof(struct sockaddr))

4.int send(int sockfd,const void*msg,int len,int flags)

flags一般为0

5.收int recv(int sockfd,void*buf,int len,unsigned int flags)

flags一般为0

三、UDP服务端编程

1.sockfd= socket(AF_INET,SOCK_DGRAM,0)

2.填充和绑定.int bind(int sockfd,struct sockaddr *my_addr,int addrlen);不懂参照上面的TCP服务端

3.int recvfrom(int sockfd,void *buf,int len,unsigned int flags,struct sockaddr* from,int *fromlen)

flags一般为0

4.int sendto(int sockfd,const void* msg,int len,unsigned int flags,const strcut sockaddr* to,int tolen);

四、UDP客户端编程

1.sockfd= socket(AF_INET,SOCK_DGRAM,0);

2.填充服务端的地址信息struct sockaddr_in* to

3.int sendto(int sockfd,const void* msg,int len,unsigned int flags,const strcut sockaddr* to,int tolen);

4.int recvfrom(int sockfd,void *buf,int len,unsigned int flags,struct sockaddr* from,int *fromlen)

flags一般为0



五.上述是linux常用的TCP和UDP的编程顺序。接下来是对一些常用的函数的使用和解释

#include<netinet/in.h>

1.uint16_t htons(unit16_t host16bit)

uint32_t htonl(unit32_t host32bit)

uinit16_t ntohs(unit16_t net16it)

uint32_t ntohs(unit32_t net32bit);

2.int inet_aton(const char*string,struct in_addr* addr); 把点分十进制的IP转化为网络字节的IP

char* inet_ntoa(struct in_addr);把 网络字节的IP转化为点分十进制的IP

还有 用于IPV6的inet_pton和inet_ntop,当然也可以用于IPV4

3.struct hostent* gethostbyname(const char* hostname)

hostname:主机名

struct hostent {
char *h_name;
char **h_aliases;
int h_addrtype;
int h_length;
char **h_addr_list;
#define h_addr h_addr_list[0]
};
h_addr是指该机的第一个IP

eg.h=gethostbyname(argv[1]))

printf("host name :%s", h->h_name);
printf("IP Address :%s",inet_ntoa(*((struct  in_addr *)h->h_addr)));
另外gethostbyaddr(),不解释
 
4. #include <sys/socket.h>
int getsockname(int sockfd , struct sockaddr * addr , socklen_t * addrlen );
getsockname() 函数用于获取一个 套接字的名字。它用于一个已捆绑或已连接 套接字s,本地地址将被返回。本调用特别适用于如下情况:未调用 bind()就调用了 connect(),这时唯有getsockname()调用可以获知系统内定的本地地址。在返回时,namelen参数包含了名字的实际字节数。
5. int getaddrinfo( const char *hostname, const char *service, const struct addrinfo *hints, struct addrinfo **result );

参数说明
hostname:一个 主机名或者地址串(IPv4的 点分十进制串或者IPv6的16进制串)
service:服务名可以是十进制的 端口号,也可以是已定义的服务名称,如ftp、http等
hints:可以是一个空 指针,也可以是一个指向某个addrinfo 结构体的指针,调用者在这个结构中填入关于期望返回的信息类型的暗示。举例来说:如果指定的服务既支持TCP也支持UDP,那么调用者可以把hints结构中的ai_socktype成员设置成SOCK_DGRAM使得返回的仅仅是适用于数据报 套接口的信息。
result:本函数通过result 指针参数返回一个指向addrinfo 结构体 链表的指针。
返回值:0——成功,非0——出错

  1. struct addrinfo {
  2.      int ai_flags; /* customize behavior */
  3.      int ai_family; /* address family */
  4.      int ai_socktype; /* socket type */
  5.      int ai_protocol; /* protocol */
  6.      socklen_t ai_addrlen; /* length in bytes of address */
  7.      struct sockaddr *ai_addr; /* address */
  8.      char *ai_canonname; /* canonical name of host */
  9.      struct addrinfo *ai_next; /* next in list */
  10.      .
  11.      .
  12.      .
  13.    }

六、高级编程,或者叫实用编程

因为我们以上connect(),recv()和send()等都是阻塞性函数,如果资源没有准备好,进程就会进入睡觉,这样就无法处理I/O多路复用了,或者没法一个线程处理了。

以下有几种方法解决这个问题:

1.setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&i,sizeof(i)) //允许重复使用本地地址与套接字进行绑定

flags = fcntl(sockfd,F_GETFL);

fcntl(sockfd,FSETEL,flags|O_NONBLOCK)

这样调用accept()没有资源可利用也不会卡住了。

2.fd_set inset,tmp_inset;

struct timeval tv;

tv.sec=

tv.usec=

( setsockopt( *fd, SOL_SOCKET, SO_REUSEADDR, &flags, sizeof(flags) )

( setsockopt( *fd, SOL_SOCKET, SO_KEEPALIVE, &flags, sizeof(flags) )

FD_ZERO(&inset)    先清空集中的描述符

FD_SET(sockfd1,&inset);

FD_SET(sockfd2,&inset);

FD_SET(sockfd3,&inset);

while(1)

count=select(MAX_SOCK_FD+1,&inset,NULL,NULL,&tv);

if(FD_ISSET(sockfd1,&inset)>0)

{

accept()

recv

send

}

if(FD_ISSET(sockfd2,&inset)>0)

{

accept()

recv

send

}

close(sock1)

close(sock2)

close(sock3)

 





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
牙科就诊管理系统利用当下成熟完善的SSM框架,使用跨平台的可开发大型商业网站的Java语言,以及最受欢迎的RDBMS应用软件之一的Mysql数据库进行程序开发。实现了用户在线查看数据。管理员管理病例管理、字典管理、公告管理、药单管理、药品管理、药品收藏管理、药品评价管理、药品订单管理、牙医管理、牙医收藏管理、牙医评价管理、牙医挂号管理、用户管理、管理员管理等功能。牙科就诊管理系统的开发根据操作人员需要设计的界面简洁美观,在功能模块布局上跟同类型网站保持一致,程序在实现基本要求功能时,也为数据信息面临的安全问题提供了一些实用的解决方案。可以说该程序在帮助管理者高效率地处理工作事务的同时,也实现了数据信息的整体化,规范化与自动化。 管理员在后台主要管理病例管理、字典管理、公告管理、药单管理、药品管理、药品收藏管理、药品评价管理、药品订单管理、牙医管理、牙医收藏管理、牙医评价管理、牙医挂号管理、用户管理、管理员管理等。 牙医列表页面,此页面提供给管理员的功能有:查看牙医、新增牙医、修改牙医、删除牙医等。公告信息管理页面提供的功能操作有:新增公告,修改公告,删除公告操作。公告类型管理页面显示所有公告类型,在此页面既可以让管理员添加新的公告信息类型,也能对已有的公告类型信息执行编辑更新,失效的公告类型信息也能让管理员快速删除。药品管理页面,此页面提供给管理员的功能有:新增药品,修改药品,删除药品。药品类型管理页面,此页面提供给管理员的功能有:新增药品类型,修改药品类型,删除药品类型。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值