(一)linux C语言TCP服务端/客户端简单编程步骤

来源:互联网 发布:linux激活虚拟网卡 编辑:程序博客网 时间:2024/06/06 02:43
头文件:
#ifndef _MYHEAD_H_#define _MYHEAD_H_#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <strings.h>#include <unistd.h>#include <errno.h>#include <sys/stat.h>#include <dirent.h>#include <sys/mman.h>#include <sys/wait.h>#include <signal.h>#include <sys/ipc.h>#include <sys/shm.h>#include <sys/msg.h>#include <sys/sem.h>#include <pthread.h>#include <semaphore.h>#include <poll.h>#include <sys/epoll.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <netinet/in.h>#endif




由上图可知,TCP的服务端 5步就能完成基本功能。TCP客户端 3步就能完成基本功能。
接下来上基本代码:具体函数的操作等等再讲。
(为了使代码步骤更直观,这里不写错误处理语句)
//TCP服务器#include"myhead.h"            //在linux下用man可以知道具体函数在什么头文件中,这里用myhead.h代替#define LISTEN_NUM 5int main(){int sockfd,new_sockfd;int size;struct sockaddr_in saddr;struct sockaddr_in caddr;size = sizeof(struct sockaddr_in);/*初始化sockaddr_in saddr*/bzero(&saddr,sizeof(saddr));   //先清零saddrsaddr.sin_family = AF_INET;//AF_INET表示IPv4的类型saddr.sin_port = htons(8888);   //绑定8888端口saddr.sin_addr.s_addr = htonl(INADDR_ANY);   //绑定本机端口sockfd = socket(AF_INET,SOCK_STREAM,0);//返回-1表示失败;bind(sockfd,(struct sockaddr*)&saddr,size);//返回-1表示失败listen(sockfd,LISTEN_NUM);  //返回-1表示失败new_sockfd = accept(sockfd,(struct sockaddr*)&caddr,&size);//返回-1表示失败write(new_sockfd,"connect sucess!",sizeof("connect sucess"));return 0;}

接下来到客户端:
//TCP客户端#include"myhead.h"int main(){char buf[50];int sockfd,size;struct sockaddr_in saddr;size = sizeof(struct sockaddr_in);bzero(&saddr,sizeof(saddr));saddr.sin_family = AF_INET;saddr.sin_port = htons(8888); //服务器绑定的端口saddr.sin_addr.s_addr = inet_addr("192.168.152.128");//服务器的IP地址sockfd = socket(AF_INET,SOCK_STREAM,0); //创建一个套接字用于连接服务器,并且这个套接字可用作对服务器操作的文件描述符。//存储服务器的信息,返回-1失败connect(sockfd,(struct sockaddr*)&saddr,size);//返回-1失败read(sockfd,buf,sizeof(buf));printf("%s\n",buf);return 0;}

------------------------------------------------------------------------------------------------分割线----------------------------------------------------------------------------------------------------------------
接下来讲讲可能会疑惑的地方:
1.我们看到上面代码的一行:bind(sockfd,(struct sockaddr*)&saddr,size);
         saddr的类型明明已经定义为 sockaddr_in,为什么在这里又要强制转换为sockaddr呢?
         因为:sockadddr_in 其实是表明这个结构体是用于 IPv4 格式的,方便赋值。而传出去的时候,格式就是sockaddr的,可不管你是IPv4还是IPv6的。

2.htons 和 htonl和inet_addr:
        h代表主机host,n代表网络net,s代码短整型,htons代表把主机序换成网络序,处理短整型处理,例如端口号
        htonl则是用于处理long型,一般用于IP号,但一般IP号都用 inet_addr()来传了,唯独htonl(INADDR_ANY),这个表示随机选择本机的IP
        inet_addr(“IP号”)作用是把 点分十进制数 转换成 长整型数,点分十进制就是 一般ip的表现形式,如192.168.1.1

------------------------------------------------------------------------------------------------分割线----------------------------------------------------------------------------------------------------------------
服务端各函数:
     1.socket():
            socket()用于创建一个socket套接字,三个参数:domain(域),type(套接字类型),protocol(协议)
                domain常用的是 AF_INET和AF_INET6对应的是IPv4,IPv6协议域。
                type 常用的是 SOCK_STREAM 和 SOCK_DGRAM 对应的是 TCP 和 UDP。
                protocol 填0即可,填0他就会自动匹配合适的协议。

    2.bind():
            bind()的作用是 绑定 socket套接字和初始化的结构体(如 struct sockaddr_in),三个参数:要绑定的套接字和结构体,和结构体的字节大小
                  注意:这里需要把结构体转换成 struct sockaddr 类型了。因为套接字绑定此结构体后是要跟外部接触的。
   
    3.listen():
           listen()的作用是开始进行监听,就像电话刚刚安装好。有2个参数:分别是 服务器的套接字,连接等待队列的最大数目。
               第一个参数好理解,那第二个参数 “连接等待队列的最大数目”是什么意思呢?
               例如这个参数为5,并不是说这个服务器只能被5个客户端连接。而是服务端同一时刻能被连的只有5个客户端。

   4.accept():
           accept()的作用是 开始接收客户端的连接,如果listen像电话刚刚安装好,那accept就是一个等待别人来电的人,当没有人(客户端)连上,就一直阻塞,等待。
          当有人(客户端)连上,就继续往下执行。


客户端:
     1.socket():这个上面已经说了,这里就不赘述了。这里是创建一个套接字,用于连接服务端
     2.connect():
              作用是 把socket套接字连上服务端,若成功,操作socket套接字就等于往服务端操作,例如往socket套接字写内容,就是往服务端写内容。

0 0
原创粉丝点击