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, );
//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))==-) {
perror("bind");
exit();
}
if(listen(ss, QUEUE) == -) {
perror("listen");
exit();
} struct sockaddr_in client_addr;
socklen_t length = sizeof(client_addr);
///成功返回非负描述字,出错返回-1
conn = accept(ss, (struct sockaddr*)&client_addr, &length);
if( conn < ) {
perror("connect");
exit();
} char buffer[];
//创建另外一个线程
//std::thread t(thread_task);
//t.join();
//char buf[1024];
//主线程
while() { // memset(buf, 0 ,sizeof(buf));
// if(fgets(buf, sizeof(buf),stdin) != NULL) {
// send(conn, buf, sizeof(buf), 0);
// } memset(buffer, ,sizeof(buffer));
int len = recv(conn, buffer, sizeof(buffer), );
if(strcmp(buffer, "exit\n") == ) break;
printf("%s", buffer);
//必须要有返回数据, 这样才算一个完整的请求
send(conn, buffer, len , );
}
close(conn);
close(ss);
return ;
}
局域网聊天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, ); ///定义sockaddr_in
struct sockaddr_in servaddr;
memset(&servaddr, , 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)) < )
{
perror("connect");
exit();
} char sendbuf[BUFFER_SIZE];
char recvbuf[BUFFER_SIZE];
while (fgets(sendbuf, sizeof(sendbuf), stdin) != NULL)
{
send(sock_cli, sendbuf, strlen(sendbuf),); ///发送
if(strcmp(sendbuf,"exit\n")==)
break;
recv(sock_cli, recvbuf, sizeof(recvbuf),); ///接收
fputs(recvbuf, stdout); memset(sendbuf, , sizeof(sendbuf));
memset(recvbuf, , sizeof(recvbuf));
} close(sock_cli);
return ;
}
客户端服务端双向异步聊天源码
以上的局域网聊天应用有一个很重要的缺点, 服务器只能显示客户端发送的消息, 却无法给客户端发送消息, 这个很尴尬;
通过使用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, );
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))==-) {
perror("bind");
exit();
}
if(listen(ss, QUEUE) == -) {
perror("listen");
exit();
} struct sockaddr_in client_addr;
socklen_t length = sizeof(client_addr);
///成功返回非负描述字,出错返回-1
int conn = accept(ss, (struct sockaddr*)&client_addr, &length);
if( conn < ) {
perror("connect");
exit();
}
while() {
/*把可读文件描述符的集合清空*/
FD_ZERO(&rfds);
/*把标准输入的文件描述符加入到集合中*/
FD_SET(, &rfds);
maxfd = ;
/*把当前连接的文件描述符加入到集合中*/
FD_SET(conn, &rfds);
/*找出文件描述符集合中最大的文件描述符*/
if(maxfd < conn)
maxfd = conn;
/*设置超时时间*/
tv.tv_sec = ;
tv.tv_usec = ;
/*等待聊天*/
retval = select(maxfd+, &rfds, NULL, NULL, &tv);
if(retval == -){
printf("select出错,客户端程序退出\n");
break;
}else if(retval == ){
printf("服务端没有任何输入信息,并且客户端也没有信息到来,waiting...\n");
continue;
}else{
/*客户端发来了消息*/
if(FD_ISSET(conn,&rfds)){
char buffer[];
memset(buffer, ,sizeof(buffer));
int len = recv(conn, buffer, sizeof(buffer), );
if(strcmp(buffer, "exit\n") == ) break;
printf("%s", buffer);
//send(conn, buffer, len , 0);把数据回发给客户端
}
/*用户输入信息了,开始处理信息并发送*/
if(FD_ISSET(, &rfds)){
char buf[];
fgets(buf, sizeof(buf), stdin);
//printf("you are send %s", buf);
send(conn, buf, sizeof(buf), );
}
}
}
close(conn);
close(ss);
return ;
}
异步聊天客户端代码:
#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, );
///定义sockaddr_in
struct sockaddr_in servaddr;
memset(&servaddr, , 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)) < )
{
perror("connect");
exit();
} while(){
/*把可读文件描述符的集合清空*/
FD_ZERO(&rfds);
/*把标准输入的文件描述符加入到集合中*/
FD_SET(, &rfds);
maxfd = ;
/*把当前连接的文件描述符加入到集合中*/
FD_SET(sock_cli, &rfds);
/*找出文件描述符集合中最大的文件描述符*/
if(maxfd < sock_cli)
maxfd = sock_cli;
/*设置超时时间*/
tv.tv_sec = ;
tv.tv_usec = ;
/*等待聊天*/
retval = select(maxfd+, &rfds, NULL, NULL, &tv);
if(retval == -){
printf("select出错,客户端程序退出\n");
break;
}else if(retval == ){
printf("客户端没有任何输入信息,并且服务器也没有信息到来,waiting...\n");
continue;
}else{
/*服务器发来了消息*/
if(FD_ISSET(sock_cli,&rfds)){
char recvbuf[BUFFER_SIZE];
int len;
len = recv(sock_cli, recvbuf, sizeof(recvbuf),);
printf("%s", recvbuf);
memset(recvbuf, , sizeof(recvbuf));
}
/*用户输入信息了,开始处理信息并发送*/
if(FD_ISSET(, &rfds)){
char sendbuf[BUFFER_SIZE];
fgets(sendbuf, sizeof(sendbuf), stdin);
send(sock_cli, sendbuf, strlen(sendbuf),); //发送
memset(sendbuf, , sizeof(sendbuf));
}
}
} close(sock_cli);
return ;
}
局域网内服务端和有限个客户端聊天源码
以上的局域网聊天只能支持一个用户, 我们还要改改, 必须是支持多用户的聊天室:
局域网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[] = {};
int z = ;
void thread_fn() {
//成功返回非负描述字,出错返回-1
int conn = accept(ss, (struct sockaddr*)&client_addr, &length);
if( conn < ) {
perror("connect");
exit();
}
//把连接保存到临时数组中;
conns[z] = conn;
z++; fd_set rfds;
struct timeval tv;
int retval, maxfd;
while() {
/*把可读文件描述符的集合清空*/
FD_ZERO(&rfds);
/*把标准输入的文件描述符加入到集合中*/
FD_SET(, &rfds);
maxfd = ;
/*把当前连接的文件描述符加入到集合中*/
FD_SET(conn, &rfds);
/*找出文件描述符集合中最大的文件描述符*/
if(maxfd < conn)
maxfd = conn;
/*设置超时时间*/
tv.tv_sec = ;
tv.tv_usec = ;
/*等待聊天*/
retval = select(maxfd+, &rfds, NULL, NULL, &tv);
if(retval == -){
printf("select出错,客户端程序退出\n");
break;
}else if(retval == ){
printf("服务端没有任何输入信息,并且客户端也没有信息到来,waiting...\n");
continue;
}else{
/*客户端发来了消息*/
if(FD_ISSET(conn,&rfds)){
char buffer[];
memset(buffer, ,sizeof(buffer));
int len = recv(conn, buffer, sizeof(buffer), );
if(strcmp(buffer, "exit\n") == ) break;
printf("%s", buffer);
//send(conn, buffer, len , 0);把数据回发给客户端
}
/*用户输入信息了,开始处理信息并发送*/
if(FD_ISSET(, &rfds)){
char buf[];
fgets(buf, sizeof(buf), stdin);
//printf("you are send %s", buf);
for(int i=; i<z; i++) {
send(conns[i], buf, sizeof(buf), );
}
}
}
}
close(conn);
}
void thread_select(int conn) {
}
int main() {
ss = socket(AF_INET, SOCK_STREAM, );
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))==-) {
perror("bind");
exit();
}
if(listen(ss, QUEUE) == -) {
perror("listen");
exit();
}
std::thread t(thread_fn);
std::thread t1(thread_fn);
t.join();
t1.join();
close(ss);
return ;
}
局域网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, );
///定义sockaddr_in
struct sockaddr_in servaddr;
memset(&servaddr, , 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)) < )
{
perror("connect");
exit();
} while(){
/*把可读文件描述符的集合清空*/
FD_ZERO(&rfds);
/*把标准输入的文件描述符加入到集合中*/
FD_SET(, &rfds);
maxfd = ;
/*把当前连接的文件描述符加入到集合中*/
FD_SET(sock_cli, &rfds);
/*找出文件描述符集合中最大的文件描述符*/
if(maxfd < sock_cli)
maxfd = sock_cli;
/*设置超时时间*/
tv.tv_sec = ;
tv.tv_usec = ;
/*等待聊天*/
retval = select(maxfd+, &rfds, NULL, NULL, &tv);
if(retval == -){
printf("select出错,客户端程序退出\n");
break;
}else if(retval == ){
printf("客户端没有任何输入信息,并且服务器也没有信息到来,waiting...\n");
continue;
}else{
/*服务器发来了消息*/
if(FD_ISSET(sock_cli,&rfds)){
char recvbuf[BUFFER_SIZE];
int len;
len = recv(sock_cli, recvbuf, sizeof(recvbuf),);
printf("%s", recvbuf);
memset(recvbuf, , sizeof(recvbuf));
}
/*用户输入信息了,开始处理信息并发送*/
if(FD_ISSET(, &rfds)){
char sendbuf[BUFFER_SIZE];
fgets(sendbuf, sizeof(sendbuf), stdin);
send(sock_cli, sendbuf, strlen(sendbuf),); //发送
memset(sendbuf, , sizeof(sendbuf));
}
}
} close(sock_cli);
return ;
}
完美异步聊天服务端和客户端源码
以上的多客户聊天不是很好, 因为只允许两个客户端连接, 体验非常差, 如果支持无限个客户端聊天的话那该多好啊, 哈哈, 这个也是可以的, 我们只要使用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(){
int conn = accept(s, (struct sockaddr*)&servaddr, &len);
li.push_back(conn);
printf("%d\n", conn);
}
} void getData() {
struct timeval tv;
tv.tv_sec = ;
tv.tv_usec = ;
while() {
std::list<int>::iterator it;
for(it=li.begin(); it!=li.end(); ++it){
fd_set rfds;
FD_ZERO(&rfds);
int maxfd = ;
int retval = ;
FD_SET(*it, &rfds);
if(maxfd < *it){
maxfd = *it;
}
retval = select(maxfd+, &rfds, NULL, NULL, &tv);
if(retval == -){
printf("select error\n");
}else if(retval == ) {
//printf("not message\n");
}else{
char buf[];
memset(buf, ,sizeof(buf));
int len = recv(*it, buf, sizeof(buf), );
printf("%s", buf);
}
}
sleep(); }
} void sendMess() {
while() {
char buf[];
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), );
}
}
} int main() {
//new socket
s = socket(AF_INET, SOCK_STREAM, );
memset(&servaddr, , 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))==-) {
perror("bind");
exit();
}
if(listen(s, ) == -) {
perror("listen");
exit();
}
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(){ }
return ;
}
无限个客户端连接的客户端代码:
#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, );
///定义sockaddr_in
struct sockaddr_in servaddr;
memset(&servaddr, , 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)) < )
{
perror("connect");
exit();
} while(){
/*把可读文件描述符的集合清空*/
FD_ZERO(&rfds);
/*把标准输入的文件描述符加入到集合中*/
FD_SET(, &rfds);
maxfd = ;
/*把当前连接的文件描述符加入到集合中*/
FD_SET(sock_cli, &rfds);
/*找出文件描述符集合中最大的文件描述符*/
if(maxfd < sock_cli)
maxfd = sock_cli;
/*设置超时时间*/
tv.tv_sec = ;
tv.tv_usec = ;
/*等待聊天*/
retval = select(maxfd+, &rfds, NULL, NULL, &tv);
if(retval == -){
printf("select出错,客户端程序退出\n");
break;
}else if(retval == ){
printf("客户端没有任何输入信息,并且服务器也没有信息到来,waiting...\n");
continue;
}else{
/*服务器发来了消息*/
if(FD_ISSET(sock_cli,&rfds)){
char recvbuf[BUFFER_SIZE];
int len;
len = recv(sock_cli, recvbuf, sizeof(recvbuf),);
printf("%s", recvbuf);
memset(recvbuf, , sizeof(recvbuf));
}
/*用户输入信息了,开始处理信息并发送*/
if(FD_ISSET(, &rfds)){
char sendbuf[BUFFER_SIZE];
fgets(sendbuf, sizeof(sendbuf), stdin);
send(sock_cli, sendbuf, strlen(sendbuf),); //发送
memset(sendbuf, , sizeof(sendbuf));
}
}
} close(sock_cli);
return ;
}
局域网通过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, );
memset(&addr_serv, , 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 ;
}
void udpserv_echo(int s, struct sockaddr* client) {
int n;
char buff[BUFF_LEN];
int len;
//printf("%p\n",&recvfrom);
while() {
socklen_t length = sizeof(client);
n = recvfrom(s, buff, BUFF_LEN, , client, &length);
printf("%s\n", buff);
//strcpy(buff, "nice to see you");
sendto(s, buff, n, , 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, , serv, len);
}
}
int main(int argc , char ** argv) {
int s;
struct sockaddr_in addr_serv;
s = socket(AF_INET, SOCK_DGRAM, );
memset(&addr_serv, , 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[]);
addr_serv.sin_port = htons(PORT_SERV);
udpclient_echo(s, (struct sockaddr*)&addr_serv);
return ;
}
获取当前进程的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 ;
}
system语句的使用:
#include <stdlib.h>
#include <stdio.h>
int main(void) {
int ret;
ret = system("ping www.baidu.com");
printf("%d\n", ret);
return ;
}
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 = ; void printMes(int signo)
{
printf("Get a SIGALRM, %d counts!\n", ++count);
} int main()
{
int res = ;
struct itimerval tick; signal(SIGALRM, printMes);
memset(&tick, , sizeof(tick)); //Timeout to run first time
tick.it_value.tv_sec = ;
tick.it_value.tv_usec = ; //After first, the Interval time for clock
tick.it_interval.tv_sec = ;
tick.it_interval.tv_usec = ;
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()
{
}
return ;
}
select的使用,通过select可以实现定时器:
static void sleep_ms(unsigned int secs){
struct timeval tval;
tval.tv_sec=secs/;
tval.tv_usec=(secs*)%;
select(,NULL,NULL,NULL,&tval);
}
select异步代码
通过select,实现socket可读或者可写的时候,然后再搞事情:
#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
int main() {
while() {
fd_set rd;
struct timeval tv;
int err; FD_ZERO(&rd);
FD_SET(, &rd); tv.tv_sec = ;
tv.tv_usec = ;
err = select(, &rd, NULL, NULL, &tv);
if(err == -) {
perror("select error()\n");
}else if(err == ) {
printf("no data is avaliable now\n");
}else{
if(FD_ISSET(, &rd)) {
char buf[];
fgets(buf, sizeof(buf), stdin);
printf("%s",buf);
}
}
}
return ;
}
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 = -;
int times = ;
int run = ;
ret = pthread_create(&pt, NULL, start, &run);
if(ret != ) {
printf("create error\n");
return ;
}
usleep();
printf("main thread\n");
pthread_join(pt, NULL);
return ;
}
获取指定网卡的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[]="/sys/class/net/"; //默认网卡路径
strcat(ifPath , str);
strcat(ifPath ,"/address");
//打开这个设备
FILE *ff = fopen(ifPath,"r");
fread(MAC,, , 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, ); //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[];
strcpy(NetInterface, argv[]);
int index = if_nametoindex ((const char*)NetInterface);
printf("index is %d\n", index); //get MAC, 要设置初始值
char MAC[]={};
char end[] = "";
getMac(MAC, argv[]);
printf("%s\n", MAC); unsigned char ip[];
getIp(ip, argv[]);
printf("\n");
return ;
}
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( - == pid ) {
printf("error \n");
}else if( pid == ) {
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 ;
}
通过使用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 = ;
const int PORT = ;
const int BACKLOG = ;
const int LISTENQ = ;
const int MAX_CONNECT = ; 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, );
if(listenFd < ){
perror("socket error");
exit(); }
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)) < ) {
perror("bind error");
exit();
};
if(listen(listenFd, LISTENQ) < ) {
perror("listen error");
exit();
};
printf("data");
while(true) {
client = sizeof(cliAddr);
connFd = accept(listenFd, (struct sockaddr*)&cliAddr, &client);
if(connFd < ) {
perror("accept error");
exit();
}
childPid =fork();
if(childPid == ) {
close(listenFd);
char buf[MAX_LINE];
while(read(connFd, buf, MAX_LINE) > ) {
printf("data is %s", buf);
memset(buf, ,sizeof(buf));
};
}
}
close(listenFd);
return ;
}
客户端代码:
#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 = ;
const int PORT = ;
const int BACKLOG = ;
const int LISTENQ = ;
const int MAX_CONNECT = ; int main(int argc , char **argv) {
int sockFd;
struct sockaddr_in serAddr;
if( argc != ) {
perror("args error");
exit();
}
sockFd = socket(AF_INET, SOCK_STREAM, );
if(sockFd < ) {
perror("socket error");
exit();
}
bzero(&serAddr, sizeof(serAddr));
serAddr.sin_family = AF_INET;
serAddr.sin_port = htons(PORT);
printf("%s",argv[]);
//serAddr.sin_addr.s_addr = inet_addr(argv[1]);
if(inet_pton(AF_INET , argv[] , &serAddr.sin_addr) < )
{
printf("inet_pton error for %s\n",argv[]);
exit();
}
if(connect(sockFd, (struct sockaddr*)&serAddr, sizeof(serAddr)) < ) {
perror("connect error");
exit();
};
char sendLine[MAX_LINE];
while(fgets(sendLine, MAX_LINE, stdin)!=NULL) {
write(sockFd, sendLine, strlen(sendLine));
}
close(sockFd);
return ;
}
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, );
if( fd< ){
perror("socket error");
exit();
}
bzero(&saddr , sizeof(saddr));
bzero(&caddr , sizeof(caddr));
saddr.sin_family = AF_INET;
saddr.sin_port = htons();
saddr.sin_addr.s_addr = htonl(INADDR_ANY); //bind
int bfd = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr));
if( bfd< ){
perror("bind error");
exit();
}
//listen
int lfd = listen(fd, QUEUE);
if( lfd< ){
perror("listen error");
exit();
}
//accept
socklen_t len = sizeof(caddr);
int conn = accept(fd, (struct sockaddr *)&caddr, &len);
if(conn < ){
perror("conn error");
exit();
}
char buf[SIZE]; while(read(conn, buf, SIZE) > ) {
//read
printf("%s", buf);
bzero(buf, SIZE);
} close(fd);
return ;
}
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, );
struct sockaddr_in saddr;
bzero(&saddr, sizeof(saddr));
saddr.sin_family = AF_INET;
saddr.sin_port = htons();
saddr.sin_addr.s_addr = inet_addr("127.0.0.1"); int conn;
conn = connect(fd, (struct sockaddr*)&saddr, sizeof(saddr));
if( conn< ) {
perror("error");
exit();
}
char buf[SIZE];
while(fgets(buf, SIZE, stdin)!=NULL) {
printf("%s", buf);
write(fd, buf, SIZE);
bzero(buf, SIZE);
}
return ;
}
参考
c++中Socket通信函数之select : http://blog.csdn.net/piaojun_pj/article/details/5991968/
EOF
作者: NONO
出处:http://www.cnblogs.com/diligenceday/
QQ:287101329
微信:18101055830
linux:C++的socket编程的更多相关文章
- Linux学习之socket编程(二)
Linux学习之socket编程(二) 1.C/S模型——UDP UDP处理模型 由于UDP不需要维护连接,程序逻辑简单了很多,但是UDP协议是不可靠的,实际上有很多保证通讯可靠性的机制需要在应用层实 ...
- Linux学习之socket编程(一)
socket编程 socket的概念: 在TCP/IP协议中,“IP地址+TCP或UDP端口号”唯一标识网络通讯中的一个进程,“IP地址+端口号”就称为socket. 在TCP协议中,建立连接的两个进 ...
- Linux下Golang Socket编程原理分析与代码实现
在POSIX标准推出后,socket在各大主流OS平台上都得到了很好的支持.而Golang是自带Runtime的跨平台编程语言,Go中提供给开发者的Socket API是建立在操作系统原生Socket ...
- Linux 应用开发----socket编程笔记
Linux socket编程 套接字定义描述 套接字的域 AF_INET ====>IPv4 AF_INET6 ====>IPv6 AF_UNIX ====>unix 域 AF_UP ...
- LINUX 下 ipv6 socket 编程
大家都知道,随着互联网上主机数量的增多,现有的32位IP地址已经不够用了,所以推出了下一代IP地址IPv6,写网络程序的要稍微改变一下现有的网络程序适应IPv6网络是相当容易的事.对于我们来说就是IP ...
- Linux下网络socket编程——实现服务器(select)与多个客户端通信
一.关于socket通信 服务器端工作流程: 调用 socket() 函数创建套接字 用 bind() 函数将创建的套接字与服务端IP地址绑定 调用listen()函数监听socket() 函数创建的 ...
- Linux基础(05)socket编程
Linux的核心思想之一 "一切皆文件" 内容 , socket在Linux内核的实现的代码及TCP和UDP的实现 网络编程常用头文件: https://blog.csdn.net ...
- Linux - 非阻塞socket编程处理EAGAIN错误
在linux进行非阻塞的socket接收数据时经常出现Resource temporarily unavailable,errno代码为11(EAGAIN),这表明你在非阻塞模式下调用 ...
- Linux IPC BSD socket编程基础
头文件 #include<unistd.h> #include <sys/types.h> #include <sys/socket.h> #include< ...
- 网络编程学习笔记:linux下的socket编程
socket是进程通信的一种方式,通过调用一些API可以实现进程间通信,建立连接以及收发信息的过程如下图所示: 这些函数的用法如下: 1.int socket(int protocolFamily, ...
随机推荐
- 如何自定义 maven中的archetype
1.首先使用eclipse创建一个新的maven project,然后把配置好的一些公用的东西放到相应的目录下面 比如说会将一些常用的java代码存放到src/main/java目录下面: 会将一些通 ...
- Revit Family API 找到实体某一方向上的面。
PlanarFace.Normal取得向量.IsAlmostEqualTo判断向量是否一致. // ================================================== ...
- 解决克隆 centos虚拟机后修改克隆后的机器的ip、mac、uuid失败的问题
解决办法: So here's how we fix it: Remove the kernel's networking interface rules file so that it ca ...
- myeclipse 2014 专业版 安装 svn插件
团队合作的项目肯定少不了版本控制,那么现在就看看myeclispe中是如何使用的吧. 开发环境:myeclipse 2014 java 8 tomcate 8 试了网上说的几种方法,都没有成功,最 ...
- Linux 用户和用户操作
1,创建组 groupadd test 增加一个test组 2,修改组 groupmod -n test2 test 将test组的名子改成test2 3,删除组 groupdel test2 删除 ...
- 查看Oracle数据库名和实例名的命令
查看数据库名 SQL> select name from v$database; NAME --------- ORCL SQL> desc v$database; 名称 ...
- ASP.NET MVC:mvc pattern
There are three pieces to the MVC pattern: The model—The domain that your software is built around. ...
- Eclipse 保存文件时自动格式化代码
很多同学不知道Eclipse有个很有用的功能,就是自动格式源代码的功能,一般大家都是直接Ctrl+Shift+F手动格式化,多浪费时间. 其实Eclipse里已经带有自动格式化功能了,默认是没有代开该 ...
- libgdx 环境搭建
1:环境搭建: (1)首先进入官网,http://libgdx.badlogicgames.com/download.html 点击下方的Releases.进行下载最新的版本号就可以. 这个为我们开 ...
- [Android Security] DEX文件格式分析
copy from : https://segmentfault.com/a/1190000007652937 0x00 前言 分析 dex 文件格式最好的方式是找个介绍文档,自己再写一个简单的 de ...