Socket | C语言 | Linux | 网络编程 | 实战(一)_我是一块小石头-CSDN博客
Socket | C语言 | Linux | 网络编程 | 实战(二)_我是一块小石头-CSDN博客
Socket | C语言 | Linux | 网络编程 | 实战(三)_我是一块小石头-CSDN博客
实例
通过pthread创建线程来实现了一个1对1的client/server的交互。
Client创建一个thread来读取Server发送过来的消息。
Server创建一个thread来发送消息给Client
quit/allquit退出
编译过程中会遇到动态链接pthread的错误。
如果是make编译,需要添加--pthread
用automake编译,需要在configure.ac
中添加如下
# pthread
AC_CHECK_LIB([pthread], [pthread_create], [], [AC_MSG_ERROR([pthread is missing])])
PTHREAD_CFLAGS=-pthread
AC_SUBST(PTHREAD_CFLAGS)
Client
/*代码里面有部分我对驱动程序的相关控制*/
/*socket端*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#define MAXBUF 1024
#define DEV_IOC_MAGIC '0xee' //定义幻数
#define DEV_IOCPRINT _IO(DEV_IOC_MAGIC, 1)
#define DEV_IO_HIGH _IO(DEV_IOC_MAGIC, 2)
#define DEV_IO_LOW _IO(DEV_IOC_MAGIC, 3)
#define DEV_IOC_MAXNR 3
char send_buf[MAXBUF+1];
int fd;
void *thread(void *x)
{
int cmd;
char buf[BUFSIZ];
int new_fd = *((int*)x);
while(recv(new_fd,buf,BUFSIZ,0)>0)
{
//int len=recv(new_fd,buf,BUFSIZ,0);
if(strcmp(buf,"1")==0)
{
printf("<--- Call DEV_IO_HIGH --->\n");
cmd = DEV_IO_HIGH;
if (ioctl(fd, cmd) < 0)
{
printf("Call cmd DEV_IO_HIGH fail\n");
}
printf("NOW,GPIO is High.\n");
}
if(strcmp(buf,"0")==0)
{
printf("<--- Call DEV_IO_LOW --->\n");
cmd = DEV_IO_LOW;
if (ioctl(fd, cmd) < 0)
{
printf("Call cmd DEV_IO_LOW fail\n");
}
printf("NOW,GPIO is Low.\n");
}
printf("client:received:%s\n",buf);
}
/*while(1)
{
bzero(send_buf, MAXBUF + 1);
scanf("%s",send_buf);
send(new_fd, send_buf, strlen(send_buf), 0); //第 4 步 向套接字中写入字符串
}*/
return NULL;
}
bool open_dev()
{
fd = open("rec_msg", O_CREAT | O_RDWR | O_APPEND,0600);
if(fd < 0){
printf("rec_msg is open fail!\n");
return false;
}
return true;
}
int main(int argc, char *argv[])
{
int client_sockfd;
int len;
struct sockaddr_in remote_addr; //服务器端网络地址结构体
char buf[BUFSIZ]; //数据传送的缓冲区
memset(&remote_addr,0,sizeof(remote_addr)); //数据初始化--清零
remote_addr.sin_family=AF_INET; //设置为IP通信
remote_addr.sin_addr.s_addr=inet_addr("0.0.0.0");//服务器IP地址
remote_addr.sin_port=htons(8000); //服务器端口号
bool flag = open_dev();
if(!flag){
printf("client closed because of failure of opening rec_msg file\n");
return 1;
}
/*创建客户端套接字--IPv4协议,面向连接通信,TCP协议*/
if((client_sockfd=socket(PF_INET,SOCK_STREAM,0))<0)
{
perror("socket error");
return 1;
}
/*将套接字绑定到服务器的网络地址上*/
if(connect(client_sockfd,(struct sockaddr *)&remote_addr,sizeof(struct sockaddr))<0)
{
perror("connect error");
return 1;
}
printf("connected to server\n");
//len=recv(client_sockfd,buf,BUFSIZ,0);//接收服务器端信息
// buf[len]='\0';
//printf("%s",buf); //打印服务器端信息
//新建一个线程来进行接收操作.
pthread_t ntid;
pthread_create(&ntid,NULL,thread,&client_sockfd);
/*循环的发送接收信息并打印接收信息--recv返回接收到的字节数,send返回发送的字节数*/
while(1)
{
//printf("Enter string to send:");
scanf("%s",buf);
if(send(client_sockfd,buf,strlen(buf),0)<0){
perror("send message error: %s errno : %d");
return 1;
}
//len=recv(client_sockfd,buf,BUFSIZ,0);
//buf[len]='\0';
//printf("received:%s\n",buf);
printf("client:send ok.\n");
if(strcmp(buf,"quit") == 0 ||strcmp(buf, "allquit") == 0){
printf("End conversation.\n");
break;
}
}
close(client_sockfd);//关闭套接字
client_sockfd = -1;
return 0;
}
Server
/*服务端*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#define MAXBUF 1024
char recv_buf[MAXBUF+1];
char link_state=1;
int aa;
void *fun(int x)
{
int new_fd=x;//(int)(*((int*)x));
while(1)
{
bzero(recv_buf, MAXBUF + 1);
scanf("%s",recv_buf);
int len = send(new_fd, recv_buf, sizeof(recv_buf) , 0);
printf("server:send ok\n");
if(len<=0)
break;
}
exit(0);
}
int main(int argc, char *argv[])
{
int server_sockfd;//服务器端套接字
int client_sockfd;//客户端套接字
int len;
struct sockaddr_in my_addr; //服务器网络地址结构体
char buf[BUFSIZ]; //数据传送的缓冲区
memset(&my_addr,0,sizeof(my_addr)); //数据初始化--清零
my_addr.sin_family=AF_INET; //设置为IP通信
my_addr.sin_addr.s_addr=INADDR_ANY;//服务器IP地址--允许连接到所有本地地址上
my_addr.sin_port=htons(8000); //服务器端口号
/*创建服务器端套接字--IPv4协议,面向连接通信,TCP协议*/
if((server_sockfd=socket(PF_INET,SOCK_STREAM,0))<0)
{
perror("socket error");
return 1;
}
/*将套接字绑定到服务器的网络地址上*/
if (bind(server_sockfd,(struct sockaddr *)&my_addr,sizeof(struct sockaddr))<0)
{
perror("bind error");
return 1;
}
/*监听连接请求--监听队列长度为5*/
listen(server_sockfd,5);
bool flag = true;
while(flag) {
struct sockaddr_in remote_addr; //客户端网络地址结构体
socklen_t sin_size = sizeof(remote_addr);
/*等待客户端连接请求到达*/
if((client_sockfd=accept(server_sockfd,(struct sockaddr *)&remote_addr,&sin_size))<0)
{
perror("accept");
return 1;
}
printf("accept client %s\n",inet_ntoa(remote_addr.sin_addr));
aa=client_sockfd;//可以直接传递client_sockfd.
//创建线程为了给客户端发送数据
pthread_t ntid;
int a = pthread_create(&ntid,NULL,fun,aa);
if(a=0)
printf("ok\n");
while(1){
memset(buf,0,sizeof buf);
/*接收客户端的数据并将其发送给客户端--recv返回接收到的字节数,send返回发送的字节数*/
int recv_len = recv(client_sockfd,buf,BUFSIZ,0);
if(recv_len<0){
perror("recv error %s errno: %d\n");
continue;
}
//添加char[]结束标志
buf[recv_len] = '\0';
printf("server:recvived:%s\n",buf);
if(strcmp(buf,"quit")==0){
printf("Conversation will be closed.\n");
break;
}
if(strcmp(buf,"allquit")==0){
printf("Server will be closed.\n");
flag = false;
break;
}
}
close(client_sockfd);
client_sockfd = -1;
}
close(server_sockfd);
server_sockfd=-1;
return 0;
}