linux:C++的socket编程
基本的局域网聊天
局域网聊天TCP服务端:
运行下面代码
#include <sys/types.h> #include <sys/socket.h> #include <stdio.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <fcntl.h> #include <sys/shm.h> #include <thread> #include <iostream> #define PORT 7000 #define QUEUE 20 int conn; void thread_task() { } int main() { //printf("%d\n",AF_INET); //printf("%d\n",SOCK_STREAM); int ss = socket(AF_INET, SOCK_STREAM, 0); //printf("%d\n",ss); struct sockaddr_in server_sockaddr; server_sockaddr.sin_family = AF_INET; server_sockaddr.sin_port = htons(PORT); //printf("%d\n",INADDR_ANY); server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY); if(bind(ss, (struct sockaddr* ) &server_sockaddr, sizeof(server_sockaddr))==-1) { perror("bind"); exit(1); } if(listen(ss, QUEUE) == -1) { perror("listen"); exit(1); } struct sockaddr_in client_addr; socklen_t length = sizeof(client_addr); ///成功返回非负描述字,出错返回-1 conn = accept(ss, (struct sockaddr*)&client_addr, &length); if( conn < 0 ) { perror("connect"); exit(1); } char buffer[1024]; //创建另外一个线程 //std::thread t(thread_task); //t.join(); //char buf[1024]; //主线程 while(1) { // memset(buf, 0 ,sizeof(buf)); // if(fgets(buf, sizeof(buf),stdin) != NULL) { // send(conn, buf, sizeof(buf), 0); // } memset(buffer, 0 ,sizeof(buffer)); int len = recv(conn, buffer, sizeof(buffer), 0); if(strcmp(buffer, "exit\n") == 0) break; printf("%s", buffer); //必须要有返回数据, 这样才算一个完整的请求 send(conn, buffer, len , 0); } close(conn); close(ss); return 0; }
局域网聊天TCP客户端:
运行下面代码
#include <sys/types.h> #include <sys/socket.h> #include <stdio.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <fcntl.h> #include <sys/shm.h> #define MYPORT 7000 #define BUFFER_SIZE 1024 int main() { ///定义sockfd int sock_cli = socket(AF_INET,SOCK_STREAM, 0); ///定义sockaddr_in struct sockaddr_in servaddr; memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(MYPORT); ///服务器端口 servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); ///服务器ip //连接服务器,成功返回0,错误返回-1 if (connect(sock_cli, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) { perror("connect"); exit(1); } char sendbuf[BUFFER_SIZE]; char recvbuf[BUFFER_SIZE]; while (fgets(sendbuf, sizeof(sendbuf), stdin) != NULL) { send(sock_cli, sendbuf, strlen(sendbuf),0); ///发送 if(strcmp(sendbuf,"exit\n")==0) break; recv(sock_cli, recvbuf, sizeof(recvbuf),0); ///接收 fputs(recvbuf, stdout); memset(sendbuf, 0, sizeof(sendbuf)); memset(recvbuf, 0, sizeof(recvbuf)); } close(sock_cli); return 0; }
客户端服务端双向异步聊天源码
以上的局域网聊天应用有一个很重要的缺点, 服务器只能显示客户端发送的消息, 却无法给客户端发送消息, 这个很尴尬;
通过使用C中的select()函数, 实现一个异步聊天工具:
异步聊天服务端代码:
运行下面代码
#include <sys/types.h> #include <sys/socket.h> #include <stdio.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <fcntl.h> #include <sys/shm.h> #include <iostream> #define PORT 7000 #define QUEUE 20 int main() { fd_set rfds; struct timeval tv; int retval, maxfd; int ss = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in server_sockaddr; server_sockaddr.sin_family = AF_INET; server_sockaddr.sin_port = htons(PORT); //printf("%d\n",INADDR_ANY); server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY); if(bind(ss, (struct sockaddr* ) &server_sockaddr, sizeof(server_sockaddr))==-1) { perror("bind"); exit(1); } if(listen(ss, QUEUE) == -1) { perror("listen"); exit(1); } struct sockaddr_in client_addr; socklen_t length = sizeof(client_addr); ///成功返回非负描述字,出错返回-1 int conn = accept(ss, (struct sockaddr*)&client_addr, &length); if( conn < 0 ) { perror("connect"); exit(1); } while(1) { /*把可读文件描述符的集合清空*/ FD_ZERO(&rfds); /*把标准输入的文件描述符加入到集合中*/ FD_SET(0, &rfds); maxfd = 0; /*把当前连接的文件描述符加入到集合中*/ FD_SET(conn, &rfds); /*找出文件描述符集合中最大的文件描述符*/ if(maxfd < conn) maxfd = conn; /*设置超时时间*/ tv.tv_sec = 5; tv.tv_usec = 0; /*等待聊天*/ retval = select(maxfd+1, &rfds, NULL, NULL, &tv); if(retval == -1){ printf("select出错,客户端程序退出\n"); break; }else if(retval == 0){ printf("服务端没有任何输入信息,并且客户端也没有信息到来,waiting...\n"); continue; }else{ /*客户端发来了消息*/ if(FD_ISSET(conn,&rfds)){ char buffer[1024]; memset(buffer, 0 ,sizeof(buffer)); int len = recv(conn, buffer, sizeof(buffer), 0); if(strcmp(buffer, "exit\n") == 0) break; printf("%s", buffer); //send(conn, buffer, len , 0);把数据回发给客户端 } /*用户输入信息了,开始处理信息并发送*/ if(FD_ISSET(0, &rfds)){ char buf[1024]; fgets(buf, sizeof(buf), stdin); //printf("you are send %s", buf); send(conn, buf, sizeof(buf), 0); } } } close(conn); close(ss); return 0; }
异步聊天客户端代码:
运行下面代码
#include <sys/types.h> #include <sys/socket.h> #include <stdio.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <fcntl.h> #include <sys/shm.h> #define MYPORT 7000 #define BUFFER_SIZE 1024 int main() { int sock_cli; fd_set rfds; struct timeval tv; int retval, maxfd; ///定义sockfd sock_cli = socket(AF_INET,SOCK_STREAM, 0); ///定义sockaddr_in struct sockaddr_in servaddr; memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(MYPORT); ///服务器端口 servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); ///服务器ip //连接服务器,成功返回0,错误返回-1 if (connect(sock_cli, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) { perror("connect"); exit(1); } while(1){ /*把可读文件描述符的集合清空*/ FD_ZERO(&rfds); /*把标准输入的文件描述符加入到集合中*/ FD_SET(0, &rfds); maxfd = 0; /*把当前连接的文件描述符加入到集合中*/ FD_SET(sock_cli, &rfds); /*找出文件描述符集合中最大的文件描述符*/ if(maxfd < sock_cli) maxfd = sock_cli; /*设置超时时间*/ tv.tv_sec = 5; tv.tv_usec = 0; /*等待聊天*/ retval = select(maxfd+1, &rfds, NULL, NULL, &tv); if(retval == -1){ printf("select出错,客户端程序退出\n"); break; }else if(retval == 0){ printf("客户端没有任何输入信息,并且服务器也没有信息到来,waiting...\n"); continue; }else{ /*服务器发来了消息*/ if(FD_ISSET(sock_cli,&rfds)){ char recvbuf[BUFFER_SIZE]; int len; len = recv(sock_cli, recvbuf, sizeof(recvbuf),0); printf("%s", recvbuf); memset(recvbuf, 0, sizeof(recvbuf)); } /*用户输入信息了,开始处理信息并发送*/ if(FD_ISSET(0, &rfds)){ char sendbuf[BUFFER_SIZE]; fgets(sendbuf, sizeof(sendbuf), stdin); send(sock_cli, sendbuf, strlen(sendbuf),0); //发送 memset(sendbuf, 0, sizeof(sendbuf)); } } } close(sock_cli); return 0; }
局域网内服务端和有限个客户端聊天源码
以上的局域网聊天只能支持一个用户, 我们还要改改, 必须是支持多用户的聊天室:
局域网TCP多人聊天服务端代码:
运行下面代码
#include <sys/types.h> #include <sys/socket.h> #include <stdio.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <fcntl.h> #include <sys/shm.h> #include <iostream> #include <thread> #define PORT 7000 #define QUEUE 20 int ss; struct sockaddr_in client_addr; socklen_t length = sizeof(client_addr); int conns[2] = {}; int z = 0; void thread_fn() { //成功返回非负描述字,出错返回-1 int conn = accept(ss, (struct sockaddr*)&client_addr, &length); if( conn < 0 ) { perror("connect"); exit(1); } //把连接保存到临时数组中; conns[z] = conn; z++; fd_set rfds; struct timeval tv; int retval, maxfd; while(1) { /*把可读文件描述符的集合清空*/ FD_ZERO(&rfds); /*把标准输入的文件描述符加入到集合中*/ FD_SET(0, &rfds); maxfd = 0; /*把当前连接的文件描述符加入到集合中*/ FD_SET(conn, &rfds); /*找出文件描述符集合中最大的文件描述符*/ if(maxfd < conn) maxfd = conn; /*设置超时时间*/ tv.tv_sec = 5; tv.tv_usec = 0; /*等待聊天*/ retval = select(maxfd+1, &rfds, NULL, NULL, &tv); if(retval == -1){ printf("select出错,客户端程序退出\n"); break; }else if(retval == 0){ printf("服务端没有任何输入信息,并且客户端也没有信息到来,waiting...\n"); continue; }else{ /*客户端发来了消息*/ if(FD_ISSET(conn,&rfds)){ char buffer[1024]; memset(buffer, 0 ,sizeof(buffer)); int len = recv(conn, buffer, sizeof(buffer), 0); if(strcmp(buffer, "exit\n") == 0) break; printf("%s", buffer); //send(conn, buffer, len , 0);把数据回发给客户端 } /*用户输入信息了,开始处理信息并发送*/ if(FD_ISSET(0, &rfds)){ char buf[1024]; fgets(buf, sizeof(buf), stdin); //printf("you are send %s", buf); for(int i=0; i<z; i++) { send(conns[i], buf, sizeof(buf), 0); } } } } close(conn); } void thread_select(int conn) { } int main() { ss = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in server_sockaddr; server_sockaddr.sin_family = AF_INET; server_sockaddr.sin_port = htons(PORT); //printf("%d\n",INADDR_ANY); server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY); if(bind(ss, (struct sockaddr* ) &server_sockaddr, sizeof(server_sockaddr))==-1) { perror("bind"); exit(1); } if(listen(ss, QUEUE) == -1) { perror("listen"); exit(1); } std::thread t(thread_fn); std::thread t1(thread_fn); t.join(); t1.join(); close(ss); return 0; }
局域网TCP多人聊天客户端代码:
运行下面代码
#include <sys/types.h> #include <sys/socket.h> #include <stdio.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <fcntl.h> #include <sys/shm.h> #define MYPORT 7000 #define BUFFER_SIZE 1024 int main() { int sock_cli; fd_set rfds; struct timeval tv; int retval, maxfd; ///定义sockfd sock_cli = socket(AF_INET,SOCK_STREAM, 0); ///定义sockaddr_in struct sockaddr_in servaddr; memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(MYPORT); ///服务器端口 servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); ///服务器ip //连接服务器,成功返回0,错误返回-1 if (connect(sock_cli, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) { perror("connect"); exit(1); } while(1){ /*把可读文件描述符的集合清空*/ FD_ZERO(&rfds); /*把标准输入的文件描述符加入到集合中*/ FD_SET(0, &rfds); maxfd = 0; /*把当前连接的文件描述符加入到集合中*/ FD_SET(sock_cli, &rfds); /*找出文件描述符集合中最大的文件描述符*/ if(maxfd < sock_cli) maxfd = sock_cli; /*设置超时时间*/ tv.tv_sec = 5; tv.tv_usec = 0; /*等待聊天*/ retval = select(maxfd+1, &rfds, NULL, NULL, &tv); if(retval == -1){ printf("select出错,客户端程序退出\n"); break; }else if(retval == 0){ printf("客户端没有任何输入信息,并且服务器也没有信息到来,waiting...\n"); continue; }else{ /*服务器发来了消息*/ if(FD_ISSET(sock_cli,&rfds)){ char recvbuf[BUFFER_SIZE]; int len; len = recv(sock_cli, recvbuf, sizeof(recvbuf),0); printf("%s", recvbuf); memset(recvbuf, 0, sizeof(recvbuf)); } /*用户输入信息了,开始处理信息并发送*/ if(FD_ISSET(0, &rfds)){ char sendbuf[BUFFER_SIZE]; fgets(sendbuf, sizeof(sendbuf), stdin); send(sock_cli, sendbuf, strlen(sendbuf),0); //发送 memset(sendbuf, 0, sizeof(sendbuf)); } } } close(sock_cli); return 0; }
完美异步聊天服务端和客户端源码
以上的多客户聊天不是很好, 因为只允许两个客户端连接, 体验非常差, 如果支持无限个客户端聊天的话那该多好啊, 哈哈, 这个也是可以的, 我们只要使用c++的list即可, 它是可以自增的数组(其实算是链表), 引用 头文件<list>即可:
无限个客户聊天的 服务端代码:
运行下面代码
#include <sys/types.h> #include <sys/socket.h> #include <stdio.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <fcntl.h> #include <sys/shm.h> #include <iostream> #include <thread> #include <list> #define PORT 7000 #define IP "127.0.0.1" int s; struct sockaddr_in servaddr; socklen_t len; std::list<int> li; void getConn() { while(1){ int conn = accept(s, (struct sockaddr*)&servaddr, &len); li.push_back(conn); printf("%d\n", conn); } } void getData() { struct timeval tv; tv.tv_sec = 2; tv.tv_usec = 0; while(1) { std::list<int>::iterator it; for(it=li.begin(); it!=li.end(); ++it){ fd_set rfds; FD_ZERO(&rfds); int maxfd = 0; int retval = 0; FD_SET(*it, &rfds); if(maxfd < *it){ maxfd = *it; } retval = select(maxfd+1, &rfds, NULL, NULL, &tv); if(retval == -1){ printf("select error\n"); }else if(retval == 0) { //printf("not message\n"); }else{ char buf[1024]; memset(buf, 0 ,sizeof(buf)); int len = recv(*it, buf, sizeof(buf), 0); printf("%s", buf); } } sleep(1); } } void sendMess() { while(1) { char buf[1024]; fgets(buf, sizeof(buf), stdin); //printf("you are send %s", buf); std::list<int>::iterator it; for(it=li.begin(); it!=li.end(); ++it){ send(*it, buf, sizeof(buf), 0); } } } int main() { //new socket s = socket(AF_INET, SOCK_STREAM, 0); memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(PORT); servaddr.sin_addr.s_addr = inet_addr(IP); if(bind(s, (struct sockaddr* ) &servaddr, sizeof(servaddr))==-1) { perror("bind"); exit(1); } if(listen(s, 20) == -1) { perror("listen"); exit(1); } len = sizeof(servaddr); //thread : while ==>> accpet std::thread t(getConn); t.detach(); //printf("done\n"); //thread : input ==>> send std::thread t1(sendMess); t1.detach(); //thread : recv ==>> show std::thread t2(getData); t2.detach(); while(1){ } return 0; }
无限个客户端连接的客户端代码:
运行下面代码
#include <sys/types.h> #include <sys/socket.h> #include <stdio.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <fcntl.h> #include <sys/shm.h> #define MYPORT 7000 #define BUFFER_SIZE 1024 int main() { int sock_cli; fd_set rfds; struct timeval tv; int retval, maxfd; ///定义sockfd sock_cli = socket(AF_INET,SOCK_STREAM, 0); ///定义sockaddr_in struct sockaddr_in servaddr; memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(MYPORT); ///服务器端口 servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); ///服务器ip //连接服务器,成功返回0,错误返回-1 if (connect(sock_cli, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) { perror("connect"); exit(1); } while(1){ /*把可读文件描述符的集合清空*/ FD_ZERO(&rfds); /*把标准输入的文件描述符加入到集合中*/ FD_SET(0, &rfds); maxfd = 0; /*把当前连接的文件描述符加入到集合中*/ FD_SET(sock_cli, &rfds); /*找出文件描述符集合中最大的文件描述符*/ if(maxfd < sock_cli) maxfd = sock_cli; /*设置超时时间*/ tv.tv_sec = 5; tv.tv_usec = 0; /*等待聊天*/ retval = select(maxfd+1, &rfds, NULL, NULL, &tv); if(retval == -1){ printf("select出错,客户端程序退出\n"); break; }else if(retval == 0){ printf("客户端没有任何输入信息,并且服务器也没有信息到来,waiting...\n"); continue; }else{ /*服务器发来了消息*/ if(FD_ISSET(sock_cli,&rfds)){ char recvbuf[BUFFER_SIZE]; int len; len = recv(sock_cli, recvbuf, sizeof(recvbuf),0); printf("%s", recvbuf); memset(recvbuf, 0, sizeof(recvbuf)); } /*用户输入信息了,开始处理信息并发送*/ if(FD_ISSET(0, &rfds)){ char sendbuf[BUFFER_SIZE]; fgets(sendbuf, sizeof(sendbuf), stdin); send(sock_cli, sendbuf, strlen(sendbuf),0); //发送 memset(sendbuf, 0, sizeof(sendbuf)); } } } close(sock_cli); return 0; }
局域网通过UDP实现服务端和客户端的通信, UDP的服务端不需要执行listen函数和accept函数:
运行下面代码
#include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <string.h> #include <fcntl.h> #include <stdio.h> #include <unistd.h> #define PORT_SERV 8888 #define BUFF_LEN 256 void udpserv_echo(int s, struct sockaddr* client); int main() { int s; struct sockaddr_in addr_serv, addr_clie; s = socket(AF_INET, SOCK_DGRAM, 0); memset(&addr_serv, 0 , sizeof(addr_serv)); addr_serv.sin_family = AF_INET; addr_serv.sin_addr.s_addr = htonl(INADDR_ANY); addr_serv.sin_port = htons(PORT_SERV); bind(s, (struct sockaddr*)&addr_serv, sizeof(addr_serv)); udpserv_echo(s, (struct sockaddr*)&addr_clie); return 0; } void udpserv_echo(int s, struct sockaddr* client) { int n; char buff[BUFF_LEN]; int len; //printf("%p\n",&recvfrom); while(1) { socklen_t length = sizeof(client); n = recvfrom(s, buff, BUFF_LEN, 0 , client, &length); printf("%s\n", buff); //strcpy(buff, "nice to see you"); sendto(s, buff, n, 0, client, len); } }
UDP客户端代码, UDP客户端不需要connect函数, 但是执行sendto的时候需要指定 sockfd描述符:
运行下面代码
#include <netinet/in.h> #include <string.h> #include <fcntl.h> #include <stdio.h> #include <unistd.h> #include <arpa/inet.h> #define PORT_SERV 8888 #define BUFF_LEN 256 void udpclient_echo(int s, struct sockaddr* serv) { char buff[BUFF_LEN]; int len = sizeof(*serv); while(fgets(buff, BUFF_LEN, stdin)!=NULL) { sendto(s, buff, BUFF_LEN, 0, serv, len); } } int main(int argc , char ** argv) { int s; struct sockaddr_in addr_serv; s = socket(AF_INET, SOCK_DGRAM, 0); memset(&addr_serv, 0 , sizeof(addr_serv)); addr_serv.sin_family = AF_INET; //addr_serv.sin_addr.s_addr = htonl(INADDR_ANY); addr_serv.sin_addr.s_addr = inet_addr(argv[1]); addr_serv.sin_port = htons(PORT_SERV); udpclient_echo(s, (struct sockaddr*)&addr_serv); return 0; }
获取当前进程的ID:
运行下面代码
#include <sys/types.h> #include <unistd.h> #include <stdio.h> int main(void) { pid_t pid,ppid; pid = getpid(); ppid = getppid(); printf("pid is %d;\nppid is %d; \n",pid, ppid); return 0; }
system语句的使用:
运行下面代码
#include <stdlib.h> #include <stdio.h> int main(void) { int ret; ret = system("ping www.baidu.com"); printf("%d\n", ret); return 0; }
C++定时器
定时器, 这个是c++的语法, c的标准库中没有定时器:
运行下面代码
#include <stdio.h> //printf() #include <unistd.h> //pause() #include <signal.h> //signal() #include <string.h> //memset() #include <sys/time.h> //struct itimerval, setitimer() static int count = 0; void printMes(int signo) { printf("Get a SIGALRM, %d counts!\n", ++count); } int main() { int res = 0; struct itimerval tick; signal(SIGALRM, printMes); memset(&tick, 0, sizeof(tick)); //Timeout to run first time tick.it_value.tv_sec = 1; tick.it_value.tv_usec = 0; //After first, the Interval time for clock tick.it_interval.tv_sec = 1; tick.it_interval.tv_usec = 0; setitimer(ITIMER_REAL, &tick, NULL); //if(setitimer(ITIMER_REAL, &tick, NULL) < 0) //printf("Set timer failed!\n"); //When get a SIGALRM, the main process will enter another loop for pause() while(1) { } return 0; }
select的使用,通过select可以实现定时器:
运行下面代码
static void sleep_ms(unsigned int secs){ struct timeval tval; tval.tv_sec=secs/1000; tval.tv_usec=(secs*1000)%1000000; select(0,NULL,NULL,NULL,&tval); }
select异步代码
通过select,实现socket可读或者可写的时候,然后再搞事情:
运行下面代码
#include <stdio.h> #include <sys/time.h> #include <sys/types.h> #include <unistd.h> int main() { while(1) { fd_set rd; struct timeval tv; int err; FD_ZERO(&rd); FD_SET(0, &rd); tv.tv_sec = 5; tv.tv_usec = 0; err = select(1, &rd, NULL, NULL, &tv); if(err == -1) { perror("select error()\n"); }else if(err == 0) { printf("no data is avaliable now\n"); }else{ if(FD_ISSET(0, &rd)) { char buf[1024]; fgets(buf, sizeof(buf), stdin); printf("%s",buf); } } } return 0; }
pthead多线程
没有参数的多线程 ,假设文件名字为:ph.c ,那么要通过 gcc ph.c -o ph -w -lphread ,进行编译:
运行下面代码
#include <stdio.h> #include <string.h> #include <pthread.h> void *pfn() { printf("run\n"); } void main(int argc , char *argv[] ) { pthread_t pid, pid2; pthread_create(&pid, NULL, pfn, NULL); pthread_join(pid, NULL); }
pthead多线程编程, 使用pthead实现子程, 并给子程传递参数:
运行下面代码
#include <stdio.h> #include <pthread.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <iostream> void* start(void* args) { printf("sub thread ; the args is %d\n", *((int *)args)); return NULL; } int main(void) { pthread_t pt; int ret = -1; int times = 3; int run = 2; ret = pthread_create(&pt, NULL, start, &run); if(ret != 0) { printf("create error\n"); return 1; } usleep(1); printf("main thread\n"); pthread_join(pt, NULL); return 0; }
获取指定网卡的MAC地址和IP:
运行下面代码
#include <net/ethernet.h> #include <stdio.h> #include <sys/socket.h> #include <linux/if_packet.h> #include <net/if.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <unistd.h> #include <sys/ioctl.h> #include <netinet/ether.h> #include <netinet/in.h> #include <arpa/inet.h> void getMac(char *MAC, char *str) { char ifPath[256]="/sys/class/net/"; //默认网卡路径 strcat(ifPath , str); strcat(ifPath ,"/address"); //打开这个设备 FILE *ff = fopen(ifPath,"r"); fread(MAC,1, 17, ff); fclose(ff); } //根据网卡获取ip的通用函数 void getIp(unsigned char *ip, char *itf) { int fd; struct ifreq ifr; in_addr tIP ; fd = socket(AF_INET, SOCK_DGRAM, 0); //using ioctl get IP address ifr.ifr_addr.sa_family = AF_INET; strcpy(ifr.ifr_name , (char*)itf); ioctl(fd, SIOCGIFADDR, &ifr); close(fd); tIP =((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr; memcpy((char*)ip , &tIP ,sizeof(in_addr)); printf("ip is %s", inet_ntoa(tIP)); } int main(int argc, char *argv[]) { struct sockaddr_ll device; char NetInterface[10]; strcpy(NetInterface, argv[1]); int index = if_nametoindex ((const char*)NetInterface); printf("index is %d\n", index); //get MAC, 要设置初始值 char MAC[18]={0}; char end[] = "0"; getMac(MAC, argv[1]); printf("%s\n", MAC); unsigned char ip[4]; getIp(ip, argv[1]); printf("\n"); return 0; }
C, fork语句的使用, fork返回值为0时说明运行在拷贝线程中:
运行下面代码
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> int main() { pid_t pid; pid = fork(); if( -1 == pid ) { printf("error \n"); }else if( pid ==0 ) { printf(" fork value %d ; parent id : %d ; fork id : %d\n ", pid, getppid(), getpid()); }else{ printf(" run in parent scope, pid is %d \n", getpid()); } return 0; }
通过使用fork,可以简化服务端的代码, 局域网聊天服务端代码:
运行下面代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <sys/types.h> #include <unistd.h> #include <errno.h> #include <netinet/in.h> #include <netdb.h> #include <arpa/inet.h> const int MAX_LINE = 2048; const int PORT = 6000; const int BACKLOG = 10; const int LISTENQ = 6666; const int MAX_CONNECT = 20; int main() { struct sockaddr_in serAddr, cliAddr; int listenFd, connFd; pid_t childPid; char buf[MAX_LINE]; socklen_t client; listenFd = socket(AF_INET, SOCK_STREAM, 0); if(listenFd < 0){ perror("socket error"); exit(1); } bzero(&serAddr, sizeof(serAddr)); serAddr.sin_family = AF_INET; serAddr.sin_addr.s_addr = htonl(INADDR_ANY); serAddr.sin_port = htons(PORT); if(bind(listenFd, (struct sockaddr*)&serAddr, sizeof(serAddr)) < 0) { perror("bind error"); exit(1); }; if(listen(listenFd, LISTENQ) < 0) { perror("listen error"); exit(1); }; printf("data"); while(true) { client = sizeof(cliAddr); connFd = accept(listenFd, (struct sockaddr*)&cliAddr, &client); if(connFd < 0) { perror("accept error"); exit(1); } childPid =fork(); if(childPid == 0) { close(listenFd); char buf[MAX_LINE]; while(read(connFd, buf, MAX_LINE) > 0) { printf("data is %s", buf); memset(buf, 0 ,sizeof(buf)); }; } } close(listenFd); return 0; }
客户端代码:
运行下面代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <sys/types.h> #include <unistd.h> #include <errno.h> #include <netinet/in.h> #include <netdb.h> #include <arpa/inet.h> const int MAX_LINE = 2048; const int PORT = 6000; const int BACKLOG = 10; const int LISTENQ = 6666; const int MAX_CONNECT = 20; int main(int argc , char **argv) { int sockFd; struct sockaddr_in serAddr; if( argc != 2) { perror("args error"); exit(1); } sockFd = socket(AF_INET, SOCK_STREAM, 0); if(sockFd < 0) { perror("socket error"); exit(1); } bzero(&serAddr, sizeof(serAddr)); serAddr.sin_family = AF_INET; serAddr.sin_port = htons(PORT); printf("%s",argv[0]); //serAddr.sin_addr.s_addr = inet_addr(argv[1]); if(inet_pton(AF_INET , argv[1] , &serAddr.sin_addr) < 0) { printf("inet_pton error for %s\n",argv[1]); exit(1); } if(connect(sockFd, (struct sockaddr*)&serAddr, sizeof(serAddr)) < 0) { perror("connect error"); exit(1); }; char sendLine[MAX_LINE]; while(fgets(sendLine, MAX_LINE, stdin)!=NULL) { write(sockFd, sendLine, strlen(sendLine)); } close(sockFd); return 0; }
socket服务端:
#include <stdio.h> #include <stdlib.h> #include <sys/socket.h> #include <sys/types.h> #include <arpa/inet.h> #include <unistd.h> #include <string.h> #define QUEUE 10 #define SIZE 256 int main() { //sock fd int fd; struct sockaddr_in saddr, caddr; fd = socket(AF_INET, SOCK_STREAM, 0); if( fd<0 ){ perror("socket error"); exit(1); } bzero(&saddr , sizeof(saddr)); bzero(&caddr , sizeof(caddr)); saddr.sin_family = AF_INET; saddr.sin_port = htons(2000); saddr.sin_addr.s_addr = htonl(INADDR_ANY); //bind int bfd = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)); if( bfd<0 ){ perror("bind error"); exit(1); } //listen int lfd = listen(fd, QUEUE); if( lfd<0 ){ perror("listen error"); exit(1); } //accept socklen_t len = sizeof(caddr); int conn = accept(fd, (struct sockaddr *)&caddr, &len); if(conn < 0){ perror("conn error"); exit(1); } char buf[SIZE]; while(read(conn, buf, SIZE) > 0) { //read printf("%s", buf); bzero(buf, SIZE); } close(fd); return 0; }
socket客户端:
#include <stdio.h> #include <stdlib.h> #include <sys/socket.h> #include <sys/types.h> #include <arpa/inet.h> #include <unistd.h> #include <netdb.h> #include <string.h> #define SIZE 256 int main() { int fd; fd = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in saddr; bzero(&saddr, sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_port = htons(2000); saddr.sin_addr.s_addr = inet_addr("127.0.0.1"); int conn; conn = connect(fd, (struct sockaddr*)&saddr, sizeof(saddr)); if( conn<0 ) { perror("error"); exit(1); } char buf[SIZE]; while(fgets(buf, SIZE, stdin)!=NULL) { printf("%s", buf); write(fd, buf, SIZE); bzero(buf, SIZE); } return 0; }
参考
c++中Socket通信函数之select : http://blog.csdn.net/piaojun_pj/article/details/5991968/
EOF