linux c语言 服务器,Linux C语言实现socket服务器和客户端

一、Socket通信:

1. 含义:

Socket 是在应用层和传输层之间的一个抽象层,它把 TCP/IP 层复杂的操作抽象为几个简单的接口,供应用层调用实现进程在网络中的通信。

2. 通信流程:

cb350b01a5d71f80b132447a30946016.png

3. Socket通信部分接口说明:1. socket()

功  能:创建套接字

原  型:int socket(int domain, int type, int protocol);

参  数:

domain:协议族,通常为AF_INET,表示TCP/IP协议

type:socket类型,如:SOCK_STREAM(指TCP)和SOCK_DGRAM(指UDP)等等

protocol:套接口所用的协议,一般为0

返回值:

成功:socket文件描述符

失败:-1,并设置errno

2. bind()

功  能:将套接字和指定的端口相连

原  型:int bind(int sock_fd, struct sockaddr_in *my_addr, int addrlen);

参  数:

sock_fd:socket文件描述符

my_addr:设置服务器信息的sockaddr_in结构体指针

addrlen:sockaddr_in结构体的长度

返回值:

成功:0

失败:-1,并设置errno

说  明:

struct sockaddr_in{

short int sin_family;//网络通信网络层协议  AF_INET

unsigned short int sin_port;//端口

struct in_addr sin_addr;//IP地址

unsigned char sin_zero[8];//让sockaddr与sockaddr_in两个数据结构保持大小相同而保留的空字节

};

3. connect()

功  能:连接服务器请求(客户端使用)

原  型:int connect(int sock_fd, struct sockaddr *serv_addr,int addrlen);

参  数:

sock_fd:socket文件描述符

serv_addr:包含远端主机IP地址和端口号的指针

addrlen:sockaddr_in结构体的长度

返回值:

成功:0

失败:-1,并设置errno

4. listen()

功  能:创建一个套接口并监听申请的连接

原  型:int listen(int sock_fd, int backlog);

参  数:

sock_fd:socket文件描述符

backlog:请求队列中允许的最大请求数

返回值:

成功:0

失败:-1,并设置errno

5. accecpt()

功  能:接受客户端的服务请求

原  型:int accept(int sock_fd, struct sockadd_in* addr, int addrlen);

参  数:

sock_fd:被监听的socket文件描述符

addr:包含客户端IP地址和端口号的指针

addrlen:sockaddr_in结构体的长度

返回值:

成功:客户端套接字描述符

失败:-1,并设置errno

6. write()

功  能:写入数据到fd中

原  型:ssize_t write(int fd,const void *buf,size_t nbytes);

参  数:

fd:socket文件描述符

buf:字符串数据地址

nbytes:字符串数据大小

返回值:

实际写入的字节数,小于0为写入错误

6、read()

功  能:从fd中读取数据

原  型:ssize_t read(int fd,void *buf,size_t nbyte)

参  数:

fd:socket文件描述符

buf:字符串数据地址

nbyte:字符串数据大小

返回值:

>0: 实际读取的大小

=0:读到末尾了

<0:读取错误

8、close()

功  能:关闭套接字

原  型:int close(sock_fd);

参  数:

sock_fd:要关闭的socket文件描述符

返回值:

成功:0

失败:-1

二、线程部分接口说明:注意:Linux系统中使用线程库,编译时要加-lpthread,例如:gcc server.c -o server -lpthread

1. pthread_create()

功  能:创建线程

原  型:int pthread_create(pthread_t *thread, const pthread_attr_t *attr,

void *(*start_routine) (void *), void *arg);

参  数:

thread:线程的TID号,唯一的

attr:线程的属性

start_routine:任务函数指针,指向的函数类型 : void *func(void *)

arg:传递给任务函数使用的参数

返回值:

成功:0

失败:错误编号

2. pthread_exit()

功  能:终止调用它的线程并返回一个指向某个对象的指针(常与pthread_join()一起使用)

原  型:void pthread_exit(void *retval);

参  数:

retval:线程的退出状态值

返回值:

3. pthread_join()

功  能:以阻塞的方式等待指定的线程结束

原  型:int pthread_join(pthread_t thread, void **retval);

参  数:

thread:等待的线程的TID号

retval:用户定义的指针,用来存储被等待线程的返回值

返回值:

成功:0

失败:错误编号

4. pthread_cancel()

功  能:线程的取消

原  型:int pthread_cancel(pthread_t thread);

参  数:

thread:取消的线程的TID号

返回值:

成功:0

失败:错误编号

三、部分代码int main()

{

//1.创建网络的通信对象

socket_fd = socket(AF_INET,SOCK_STREAM,0);

if(socket_fd 

{

perror("socket error!");

return -1;

}

//2.定义服务器注册的网络端口 和 网络 IP 结构体

struct sockaddr_in server_addr,client_addr;

int len = sizeof(client_addr);

server_addr.sin_family = AF_INET;//设置网络层协议

server_addr.sin_port = htons(6666);//设置端口号

server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");//设置IP地址

//3.绑定服务器的IP地址

int ret = bind(socket_fd,(struct sockaddr *)&server_addr,sizeof(server_addr));

if(ret != 0)

{

perror("bind error!");

return -1;

}

//4.把服务器socket,设置为监听模式

ret = listen(socket_fd,5);

if(ret != 0)

{

perror("listen error!");

return -1;

}

printf("等待客户端的连接请求:\n");

//5.接收客户端的连接请求

client_fd = accept(socket_fd,(struct sockaddr *)&client_addr,&len);

if(client_fd 

{

perror("socket error!");

return -1;

}

printf("ip:%s\n",inet_ntoa(client_addr.sin_addr));

printf("port:%d\n",ntohs(client_addr.sin_port));

//创建线程

pthread_t tid;

pthread_create(&tid,NULL,sock_read,NULL);

pthread_detach(tid); //设置为分离属性

//5.发送网络数据

char buf[1024] = {0};

while(1)

{

scanf("%s",buf);

write(client_fd,buf,strlen(buf));

}

close(socket_fd);

return 0;

}

运行命令:./server和./client

四、实现效果

d479d174df3e4e382b979c7561a1c450.png

8e0da26e4817f303d71c2bc872ee4d58.png

五、总结

后续跟新以下Demo:

a6bf5ee3a18e23e0783f17d635ec8b22.png

六、项目结构图

34554333e797939ebff0e5c9a22f6c66.png

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值