Linux socket 及多线程 实例

来源:互联网 发布:叙利亚老虎师 知乎 编辑:程序博客网 时间:2024/06/05 10:48

最近开始学习linux网络通信, 学了一周了,有了一些基本的理解.下面是一个小实例.

程序很简单,服务端与客户端进行简单的通信.采用自定义通信协议,协议的格式很简单:


第一个字段是类型,如'a',表示创建新文件等

代码很简单:

server端

/* * Myserver2.cpp * *  Created on: 2015-1-9 *      Author: shuyan */#include "Myserver2.h"#include<stdio.h>#include<stdlib.h>#include<string.h>#include<errno.h>#include<sys/types.h>#include<sys/socket.h>#include<netinet/in.h>#include <unistd.h>#include <iostream>#include <pthread.h>#define DEFAULT_PORT 8007#define MAXLINE 4096using namespace std;void create_file(char * fileName, char* filePath, char * data);void * create_file_2(void * data);struct mydata {char type;int leng;char data[20];//char *data;char fileName[20];char filePath[50];};int main() {int sock_fd, connect_fd;struct sockaddr_in servaddr;char * buff = new char[4096];int n;mydata *recvData = (mydata *) malloc(sizeof(mydata));memset(recvData, 0, sizeof(mydata));memset(buff, 0, 4096);//1.if ((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {printf("create socket error: %s(errno: %d)\n", strerror(errno), errno);exit(0);}memset(&servaddr, 0, sizeof(servaddr));servaddr.sin_addr.s_addr = htonl(INADDR_ANY );servaddr.sin_port = htons(DEFAULT_PORT);servaddr.sin_family = AF_INET;//2.if (bind(sock_fd, (struct sockaddr *) &servaddr, sizeof(servaddr)) == -1) {printf("bind socket error: %s(errno: %d)\n", strerror(errno), errno);exit(0);};//3.if (listen(sock_fd, 10) == -1) {printf("listen socket error: %s(errno: %d)\n", strerror(errno), errno);exit(0);}printf("======waiting for client's request======\n");while (1) {//4.if ((connect_fd = accept(sock_fd, (struct sockaddr*) NULL, NULL)) < 0) {printf("accept socket error: %s(errno: %d)", strerror(errno),errno);continue;}//n = recv(connect_fd, buff, MAXLINE, 0);if ((n = recv(connect_fd, buff, MAXLINE, 0)) > 0) {cout << "rec Size " << n << endl;cout << "sizeof(mydata)" << sizeof(mydata);if (n >= 100) {recvData = (mydata *) buff;switch (recvData->type) {case 'a'://使用传来的数据创建新文件cout << "hahha" << endl;pthread_t pid;pthread_create(&pid, NULL, create_file_2,(void *) recvData);//pthread_join(pid,NULL);/* * 多进程 * pid_t fpid; fpid = fork(); if (fpid == 0) { printf("i am the child process, my process id is %d/n",getpid()); create_file(recvData->fileName, recvData->filePath, recvData->data); }else { printf("i am the parent process, my process id is %d/n",getpid()); }*/break;case 'b'://追加文件break;case 'c'://删除文件break;default:perror("error");break;}}}cout << "=====================" << endl;if (n == -1) {perror("receive error");}//向客户端发送回应数据if (send(connect_fd, "I received it", 16, 0) == -1) {perror("send error");}buff[n] = '\0';printf("recv msg from client\n");close(connect_fd);}close(sock_fd);}void create_file(char * fileName, char* filePath, char * data) {cout << "name:" << fileName << ",path:" << filePath << ",data:" << data<< endl;char * newName = strcat(filePath, fileName);FILE * fp;fp = fopen(newName, "w+");if (fp != NULL) {fwrite(data, sizeof(char), sizeof(data), fp);fclose(fp);}}void * create_file_2(void * data) {mydata *data_m = (struct mydata *) data;cout << "name:" << data_m->fileName << ",path:" << data_m->filePath<< ",data:" << data_m->data << endl;char * newName = strcat(data_m->filePath, data_m->fileName);FILE * fp;fp = fopen(newName, "a+");if (fp != NULL) {fwrite(data_m->data, sizeof(char), strlen(data_m->data), fp);fclose(fp);}return 0;}

客户端client

/* * Myclient2.cpp * *  Created on: 2015-1-9 *      Author: shuyan */#include "Myclient2.h"#include <sys/types.h>#include <sys/socket.h>#include<errno.h>#include<stdio.h>#include<stdlib.h>#include<string.h>#include<errno.h>#include<sys/types.h>#include<sys/socket.h>#include<netinet/in.h>#include <arpa/inet.h>#include <unistd.h>#include <iostream>#define MAXLINE 4096#define DEFAULT_PORT 8007using namespace std;int main() {char recvline[4096], sendline[4096];char buf[MAXLINE];int socket_fd;int receive_len;struct sockaddr_in servaddr;int send_num;struct mydata {char type;int leng;char data[20];char fileName[20];char filePath[50];};mydata data1 = { 'a', 10, "abcdefghij", "test.txt", "/home/shuyan/java/" };//初始化socketif ((socket_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {printf("create socket error:%s(errno:%d)\n", strerror(errno), errno);exit(0);}memset(&servaddr, 0, sizeof(servaddr));servaddr.sin_port = htons(DEFAULT_PORT);servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");//链接if (connect(socket_fd, (struct sockaddr*) &servaddr, sizeof(servaddr))< 0) {printf("connect error: %s(errno: %d)\n", strerror(errno), errno);exit(0);}printf("send msg to server: \n");/* *consle input your message *//** * fgets(sendline, 1000, stdin); if (send(socket_fd, sendline, sizeof(sendline), 0) < 0) { printf("send msg error: %s(errno: %d)\n", strerror(errno), errno); exit(0); } */if ((send_num = send(socket_fd, &data1, sizeof(data1), 0)) < 0) {printf("send msg error: %s(errno: %d)\n", strerror(errno), errno);exit(0);}cout << "send_num" << send_num << endl;if ((receive_len = recv(socket_fd, buf, MAXLINE, 0)) == -1) {perror("recv error");exit(1);}buf[receive_len] = '\0';printf("Received : %s ", buf);close(socket_fd);exit(0);}

需要注意的地方:

1.当通信传输的数据不是简单的文本而是结构体之类的复杂数据,两边都需要使用结构体对数据进行封包\解包.

2.创建多线程时,如果需要传递的参数有多个.也需要将其封装成结构体,然后在强制转换后进行传递.


0 0