Linux网络编程--线程并发

网络编程

网络编程,其实也是一种通信方式,前面我们学习的管道,消息队列,共享内存,信号,信号量,都是单机通信,也就是只能在一台电脑跑,而网络编程就可以实现多机通信,我们只需要知道ip地址,端口,socket,就可以进行通信。

socket连接协议

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

brief:创建服务端(客户端)的连接协议

param:domian,是你所使用的协议族,有AF_INET (ipv4)AF_INET6(ipv6)等,type,用那种通信协议,tcp(相当于打电话,我发过去,你接到了,我才能继续发),udp(相当于发短信,你需要发送大量数据,可以用,但它不保证消息是否可靠),protocol,用那种协议进行传输,0,根据type定义的协议,进行默认分配。

return:返回网络编程的标识符

bind绑定ip地址和端口号

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

uint16_t htons(uint16_t hostshort);//小端字节序转换网络字节序

字节序:小端字节序意思就是,低位存在低地址,大端字节序的意思就是,高位存在低地址

int inet_aton(const char *cp, struct in_addr *inp);//ip地址是一个字符串格式,网络并不认识字符串格式,所以我们要进行转换成网络认识的格式

struct sockaddr_in {

kernel_sa_family_t sin_family; //再次设置socket 的协议族 be16 sin_port; //设置端口号,但是网络字节序是大端标识符,这里我的电脑是小端标识符,所以我还要用到htnos进行转换

struct in_addr sin_addr; //一个结构体用于绑定ip地址

}

brief:对服务端(客户端)进行绑定ip地址,和端口号

param:sockfd,对哪个网络进行绑定,addr,用这个结构体绑定ip地址,端口号,addrlen,绑定的字节

return:返回0绑定成功,-1绑定失败

listen监听网络连接

int listen(int sockfd, int backlog);

breif:用于监听网络的连接

param:sockfd,对这个网络进行监听,backlong,监听的个数

return:

accept接收连接

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

brief:监听到有人连接,accept就开始接收连接

param:sockfd,接收连接到这个网络,addr,可以打印客户端的ip地址,addrlen,打印的字节数

return:接收连接成功返回一个新的标识符,我们和客户端的通信,靠这个新的标识符,返回-1,接收连接失败

read/write接收/发送消息

服务端

#include <stdio.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>

void * handler(void * fd);
struct sockaddr_in server;
struct sockaddr_in client;

void main(int argc,char ** argv)
{
        if(argc != 3)
        {
                perror("argc");
                exit(-1);
        }

        int fd;
        int bflag;
        int lflag;
        pthread_t t1;


        //1.socket

        fd = socket(AF_INET,SOCK_STREAM,0);
        if(fd < 0)
        {
                printf("socket error!\n");
        }
        else
                printf("socket succeed!\n");


        //2.bind

        server.sin_family = AF_INET;
        server.sin_port = htons(atoi(argv[2]));
        inet_aton(argv[1],&server.sin_addr);

        bflag = bind(fd,(struct sockaddr *)&server,sizeof(struct sockaddr_in));
        if(bflag < 0)
                printf("bind error!\n");
        else
                printf("bind succeed!\n");

        //3.listen

        lflag = listen(fd,5);
        if(lflag < 0)
                printf("listen error\n");
        else
                printf("listen succeed!\n");

        //4.accept

        int len = sizeof(struct sockaddr_in);
        while(1)
        {
                int new_Fd = accept(fd,(struct sockaddr *)&client,&len);
                if(new_Fd < 0)
                {
                        printf("accept error\n");
                }
                else
                {

                        pthread_create(&t1,NULL,handler,(void *)&new_Fd);
                        pthread_join(t1,NULL);

                }

        }

}

//5.read/write

void * handler(void * fd)
{

        char wBuf[128]={'\0'};
        char rBuf[128]={'\0'};
        int ret;

        printf("客户端:%s已接入\n",inet_ntoa(client.sin_addr));

        while(1)
        {
                memset(rBuf,'\0',sizeof(rBuf)+1);
                memset(wBuf,'\0',sizeof(rBuf)+1);

                ret = read(*(int *)fd,rBuf,sizeof(rBuf)+1);
                if(ret > 0)
                {
                        printf("客户端:%s:%s\n",inet_ntoa(client.sin_addr),rBuf);

                }
                else if(ret < 0)
                {
                        printf("未接收到来自:%s的消息\n",inet_ntoa(client.sin_addr));

                }
                if(!strncasecmp(rBuf,"quit",4))
                {
                        break;
                }

                printf("请发送您的消息给客户端:%s:",inet_ntoa(client.sin_addr));
                gets(wBuf);
                write(*(int *)fd,wBuf,sizeof(wBuf)+1);

        }

                printf("客户端:%s已退出会话---\n",inet_ntoa(client.sin_addr));
                close(*(int *)fd);

                printf("退出的线程号:%ld\n",pthread_self());
                pthread_exit(NULL);
}

客户端

#include <stdio.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>

int main(int argc,char **argv)
{
        if(argc != 3)
        {
                printf("error");
                exit(-1);
        }

        int fd;
        int cFlag;

        //1.socket

        fd = socket(AF_INET,SOCK_STREAM,0);
        if(fd < 0)
        {
                printf("socket error\n");
        }
        else
                printf("socket succeed!\n");

        struct sockaddr_in server;
        server.sin_family = AF_INET;
        server.sin_port = htons(atoi(argv[2]));

        inet_aton(argv[1],&server.sin_addr);

        //2.connect

        cFlag = connect(fd,(struct sockaddr*)&server,sizeof(struct sockaddr_in));
        if(cFlag < 0)
                printf("connect error!\n");
        else
                printf("connect succeed!\n");


        //3.read/write

        char wBuf[128]={'\0'};
        char rBuf[128]={'\0'};

        while(1)
        {
                memset(wBuf,'\0',sizeof(wBuf)+1);
                memset(rBuf,'\0',sizeof(wBuf)+1);

                printf("请输入您要发的消息:");
                gets(wBuf);
                write(fd,wBuf,sizeof(wBuf)+1);
                printf("发送成功!\n");

                read(fd,rBuf,sizeof(rBuf)+1);
                printf("接收来自服务端:%s:%s\n",argv[1],rBuf);

                if(!strncasecmp(rBuf,"quit",4))
                {
                        break;
                }

        }

        printf("已退出服务端---\n");
        close(fd);

        return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

No Iverson

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值