网络编程练习------简单双机通讯
2016-03-28 22:48
387 查看
环境:
服务器端:Redhat 6.4 server 64bit
客户端: Ubuntu 14.04 64bit
客户端:
1. 根据传入的参数建立socket 并与服务器建立连接。
2. 连接成功后,开两个线程,一个用于接收来自服务器端的消息;另一个用于读取用户输入,再把输入内容发送到服务器。
3. 当接收到服务器端断开消息后,退出程序。
服务器端:
1. 根据传入的参数建立socket,并等待客户端连接到来。
2. 当收到一个客户端请求时,置连接状态为1,以表示不再接收其他客户端连接请求(为了避免聊天时,不知道发给谁),开两个线程,一个用于接收客户端的消息,另一个发送消息。
3. 当服务器接收到客户端断开连接消息,把连接状态置为0,服务器可以再接收其他客户端的连接。为了避免同时改变连接状态的值,在改变连接状态的前加锁。并把发送消息线程取消。
服务器端:Redhat 6.4 server 64bit
客户端: Ubuntu 14.04 64bit
客户端:
1. 根据传入的参数建立socket 并与服务器建立连接。
2. 连接成功后,开两个线程,一个用于接收来自服务器端的消息;另一个用于读取用户输入,再把输入内容发送到服务器。
3. 当接收到服务器端断开消息后,退出程序。
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<unistd.h> #include<errno.h> #include<pthread.h> #include<sys/types.h> #include<sys/socket.h> #include<netinet/in.h> #include<arpa/inet.h> /*客户端接收线程*/ void *recvsocket(void *arg) { int st =*(int *)arg; char buf[1024]; int rc = 0; while(1) { memset(buf, 0, sizeof(buf)); rc = recv(st, buf, sizeof(buf), 0); if(rc <= 0) { exit(0); } printf("%s", buf); } return NULL; } /*客户端发送线程*/ void *sendsocket(void *arg) { int st = *(int *)arg; char buf[1024]; int rc =0; while(1) { memset(buf, 0, sizeof(buf)); read(STDIN_FILENO, buf, sizeof(buf)); rc = send(st, buf, strlen(buf), 0); if(rc <= 0) { break; } } return NULL; } int main(int arg, char **args) { if(arg < 3) { printf("usage: client ipaddress port\n"); return -1; } int port = atoi(args[2]); //创建socket int st = socket(AF_INET, SOCK_STREAM, 0); if(st == -1) { perror("create socket error:"); return -2; } //定义一个IP地址结构 struct sockaddr_in addr; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; //指定地址结构类型 addr.sin_port = htons(port); //指定端口号 addr.sin_addr.s_addr = inet_addr(args[1]); //调用connect连接指定address的服务器 if(connect(st, (struct sockaddr *)&addr, sizeof(addr)) == -1) { perror("connect error:"); return -3; } pthread_t thrd1, thrd2; pthread_create(&thrd1, NULL, recvsocket, &st); pthread_create(&thrd2, NULL, sendsocket, &st); pthread_join(thrd1, NULL); pthread_join(thrd2, NULL); return 0; }
服务器端:
1. 根据传入的参数建立socket,并等待客户端连接到来。
2. 当收到一个客户端请求时,置连接状态为1,以表示不再接收其他客户端连接请求(为了避免聊天时,不知道发给谁),开两个线程,一个用于接收客户端的消息,另一个发送消息。
3. 当服务器接收到客户端断开连接消息,把连接状态置为0,服务器可以再接收其他客户端的连接。为了避免同时改变连接状态的值,在改变连接状态的前加锁。并把发送消息线程取消。
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<unistd.h> #include<errno.h> #include<pthread.h> #include<sys/types.h> #include<sys/socket.h> #include<netinet/in.h> #include<arpa/inet.h> /*结构体:用于传送消息到线程中*/ struct ps_info { int st; pthread_t *p; }; /*标志:是否已经有客户端连接*/ int status = 0; /*锁*/ pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; /*服务器接收线程*/ void *recvsocket(void *arg) { struct ps_info ps1 = *(struct ps_info *)arg; int st =ps1.st; char buf[1024]; int rc = 0; while(1) { memset(buf, 0, sizeof(buf)); rc = recv(st, buf, sizeof(buf), 0); if(rc <= 0) { break; } printf("%s", buf); } pthread_mutex_lock(&mutex); status = 0; //把连接状态置0 pthread_mutex_unlock(&mutex); pthread_cancel(*ps1.p); //把发送线程取消 return NULL; } /*服务器发送线程*/ void *sendsocket(void *arg) { int st = *(int *)arg; char buf[1024]; int rc =0; while(1) { memset(buf, 0, sizeof(buf)); read(STDIN_FILENO, buf, sizeof(buf)); rc = send(st, buf, strlen(buf), 0); if(rc <= 0) { break; } } return NULL; } int main(int arg, char **args) { if(arg < 3) { printf("usage: client ipaddress port\n"); return -1; } int port = atoi(args[2]); /*创建socket*/ int st = socket(AF_INET, SOCK_STREAM, 0); if(st == -1) { perror("create socket error:"); return -2; } //定义一个IP地址结构 struct sockaddr_in addr; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; //指定地址结构类型 addr.sin_port = htons(port); //指定端口号 addr.sin_addr.s_addr = htonl(INADDR_ANY); if(bind(st, (struct sockaddr *)&addr, sizeof(addr)) == -1) { perror("bind error:"); return -2; } if(listen(st, 20) == -1) { perror("listen error:"); return -2; } int client_st = 0; socklen_t len =0; struct sockaddr_in client_addr; pthread_t thrd1, thrd2; while(1) { memset(&client_addr, 0, sizeof(client_st)); len = sizeof(client_addr); client_st = accept(st, (struct sockaddr *)&client_addr, &len); pthread_mutex_lock(&mutex); status++; pthread_mutex_unlock(&mutex); if(status > 1) { close(client_st); continue; } if(client_st == -1) { perror("accept error:"); return -3; } printf("accept by %s\n", inet_ntoa(client_addr.sin_addr)); struct ps_info ps1; ps1.st = client_st; ps1.p = &thrd1; pthread_create(&thrd1, NULL, recvsocket, &ps1); pthread_detach(thrd1); pthread_create(&thrd2, NULL, sendsocket, &client_st); pthread_detach(thrd2); } close(st); return 0; }
相关文章推荐
- 如何组织构建多文件 C 语言程序(二)
- 如何写好 C main 函数
- Lua和C语言的交互详解
- Lua下基本的网络编程示例
- 关于C语言中参数的传值问题
- 简要对比C语言中三个用于退出进程的函数
- 深入C++中API的问题详解
- 基于C语言string函数的详解
- C语言中fchdir()函数和rewinddir()函数的使用详解
- C语言内存对齐实例详解
- C语言编程中统计输入的行数以及单词个数的方法
- C语言自动生成enum值和名字映射代码
- 使用C语言判断英文字符大小写的方法
- c语言实现的带通配符匹配算法
- C语言实现顺序表基本操作汇总
- C语言中计算正弦的相关函数总结
- 使用C语言详解霍夫曼树数据结构
- 探讨C语言的那些小秘密之断言
- C语言实现BMP转换JPG的方法
- 深入探讨C语言中局部变量与全局变量在内存中的存放位置