當前位置:首頁 » 編程軟體 » linux多線程socket編程

linux多線程socket編程

發布時間: 2023-02-09 11:47:20

『壹』 linux socket多線程

開線程的時候初始化socket方面錯誤的可能性比較大,好好調調吧

『貳』 linux下的 socket編程問題!

第一個問題:

對,是那樣的,用open打開文件,用read讀取文件,在發送給對方,接收方接收到後,寫入文件就可以了。不過在這個過程中最好別用字元串函數,除非你很熟悉。

第二個問題

首先你得去搞清楚什麼是線程,什麼是進程,fork出來的叫進程,pthread_create出來的才叫線程。伺服器有很多種模型(多進程,多線程,select,epoll模型,這個我的blog上有,famdestiny.cublog.cn),不一定要用多進程。

給你寫了個代碼,自己先看看:

注意,在自己的目錄下創建一個叫pserverb的文件,程序會把這個文件復製成test文件。你可以自己根據需要改改

server:

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#define SERV_PORT 5358
#define MAX_CONN 10
#define BUF_LEN 1024

void str_echo(FILE *fp, int sockfd){
ssize_t nread;
int file_fd;
char buf[BUF_LEN] = {0};

file_fd = open("test", O_WRONLY | O_TRUNC | O_CREAT, 0755);
while(1) {
bzero(buf, BUF_LEN);
if((nread = read(sockfd, buf, BUF_LEN)) == -1) {
if(errno == EINTR) {
continue;
}
else {
printf("readn error: %s\n", strerror(errno));
continue;
}
}
else if (nread == 0) {
break;
}
else {
printf("%s\n", buf);
write(file_fd, buf, nread);
}
}
close(file_fd);
}

void sig_chld(int sig){
pid_t pid;
int state;
while((pid = waitpid(-1, &state, WNOHANG)) > 0){
printf("child process %d exited.", pid);
}
return;
}

int main(int argc, char **argv)
{
int listenfd, connfd;
socklen_t cliaddrlen;
pid_t childpid;
struct sockaddr_in servaddr, cliaddr;

if((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1){
printf("socket error: %s\n", strerror(errno));
return 0;
}

bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT);
if(bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1){
printf("bind error: %s\n", strerror(errno));
return 0;
}

if(listen(listenfd, MAX_CONN) == -1){
printf("listen error: %s\n", strerror(errno));
return 0;
}

signal(SIGCHLD, sig_chld);

while(1){
cliaddrlen = sizeof(cliaddr);
if((connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddrlen)) == -1){
if(errno == EINTR){
continue;
}
else{
printf("accept error: %s\n", strerror(errno));
continue;
}
}

if((childpid = fork()) == 0){
close(listenfd);
str_echo(stdin, connfd);
exit(0);
}
else if(childpid > 0){
close(connfd);
}
else{
printf("fork error!\n");
continue;
}
}
}

client:

#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>

#define SERV_ADDR "127.0.0.1"
#define SERV_PORT 5358
#define BUF_LEN 1024

void str_cli(char *path, int sockfd)
{
char sendbuf[BUF_LEN] = {0};
int fd, n;

if((fd = open("./pserverb", O_RDONLY)) == -1){
printf("%s\n", strerror(errno));
exit(0);
}
while((n = read(fd, sendbuf, BUF_LEN)) != 0) {
if(n < 0){
printf("%s\n", strerror(errno));
exit(0);
}
write(sockfd, sendbuf, n);
bzero(sendbuf, BUF_LEN);
}
close(fd);
return;
}

int main(int argc, char **argv)
{
int fd;
struct sockaddr_in servaddr;

fd = socket(AF_INET, SOCK_STREAM, 0);

bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = inet_addr(SERV_ADDR);
servaddr.sin_port = htons(SERV_PORT);

if (connect(fd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1) {
printf("connect error: %s\n", strerror(errno));
return 0;
}

str_cli(argv[1], fd);
return 0;
}

『叄』 Linux操作系統下Socket編程地址結構介紹

linux下的網路通信程序,一定要和一個結構打交道,這個結構就是socket
address。比如bind、connect等等函數都要使用socket
address結構。理解socket
address時我們要明白,其實在linux下針對於不同的socket
domain定義了一個通用的地址結構struct
sockaddr,它的具體定義為:
{unsigned
short
int
sa_family;char
sa_data[14];}
struct
sockaddr
其中,sa_family為調用socket()函數時的參數domain參數,sa_data為14個字元長度存儲。針對於不同domain下的socket,通用地址結構又對應了不同的定義,例如一般的AF_INET
domain下,socket
address的定義如下:
struct
sockaddr_in{unsigned
short
int
sin_family;uint16_t
sin_port;struct
in_addr
sin_addr;unsigned
char
sin_zero[8];//未使用}struct
in_addr{uint32_t
s_addr;}
當socket的domain不同於AF_INET時,具體的地址定義又是不同的,但是整個地址結構的大小、容量都是和通用地址結構一致的。

『肆』 剛介入linux c的socket編程沒多久,想要寫一個socket客戶端,實現多線程處理發送和接收,哪位大俠幫幫忙啊

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define PORT 8888

void *yourfunction(void *connect_fd)
{
int connfd = *((int *)connect_fd);
。。。。
} //你沒說具體的應用,所以只能寫這么多了。在這裡面直接對connfd調用read和write函數就可以和客戶端收發數據了。

//補充:是啊 返回給客戶端什麼信息啊?

int main(void)
{
int sockfd, n, connfd;
pthread_t tid;
struct sockaddr_in servaddr;

sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1)
{
perror("socket:");
exit(1);
}

bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(PORT);

n = bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
if (n == -1)
{
perror("bind:");
exit(1);
}

n = listen(sockfd, 20);
if (n == -1)
{
perror("listen:");
exit(1);
}

while (1)
{
connfd = accept(sockfd, (struct sockaddr *)&servaddr, NULL);
pthread_create(&tid, NULL, yourfunction, (void *)&connfd);
}

return 0;
}

『伍』 linux c socket 如何實現一個進程多個線程,每個線程管理多個socket連接

大家仔細看,樓主的題目還是很有難度的呢,一個進程多個線程容易實現,但是要讓這些線程中每個線程都管理多個socket連接,確實比較難~~坐等高手。
不過一般都是一個線程處理一個socket連接,這種例子是:
(取自書上,僅供學習,直接編譯肯定通不過,少書上其他代碼)
==================================================
/* include serv06 */#include "unpthread.h"
intmain(int argc, char **argv)
{
int listenfd, connfd;
void sig_int(int);
void *doit(void *);
pthread_t tid;
socklen_t clilen, addrlen;
struct sockaddr *cliaddr;

if (argc == 2) listenfd = Tcp_listen(NULL, argv[1], &addrlen);
else if (argc == 3)
listenfd = Tcp_listen(argv[1], argv[2], &addrlen);
else
err_quit("usage: serv06 [ <host> ] <port#>");
cliaddr = Malloc(addrlen);

Signal(SIGINT, sig_int);
for ( ; ; ) { clilen = addrlen;
connfd = Accept(listenfd, cliaddr, &clilen);

Pthread_create(&tid, NULL, &doit, (void *) connfd); }
}

void *doit(void *arg)
{
void web_child(int);

Pthread_detach(pthread_self()); web_child((int) arg);
Close((int) arg);
return(NULL);
}
/* end serv06 */

voidsig_int(int signo)
{
void pr_cpu_time(void);

pr_cpu_time(); exit(0);
}
================================================================

『陸』 linux socket 編程

這類問題,你不用考慮太復雜的,可以直接使用socket提供的tcp服務介面,通過send和recv等函數處理就行了。數據建議自行寫封裝和解封函數,
介面類似這樣:int pack(char *, struct data *); int unpack(char *, struct data *);
可以按照你自己的喜好,將你的struct按照你的方式填入一個char*裡面(你直接將struct data*類型轉換後賦值給char*類型都行),然後就可以使用介面了;
你完全不用管tcp的實現機制的,tcp有擁塞控制,超時重傳,自動分包等機制,可以保證你的數據按准確的方式送達;
像什麼包的數據頭什麼的,如果你需要定義的是應用層的協議,或者你希望自定義網路層和傳輸層(使用raw方式的socket),你才需要考慮;

『柒』 Windows Socket和Linux Socket編程的區別

1)頭文件
windows下winsock.h/winsock2.h
linux下sys/socket.h
錯誤處理:errno.h
其他常用函數的頭文件可到命令行下用man指令查詢。
2)初始化
windows下需要用WSAStartup
linux下不需要(很方便),直接可以使用
3)關閉socket
windows下closesocket(...)
linux下close(...)
4)類型
windows下SOCKET
在linux下為int類型
5)綁定地址的結構體
名稱相同,都是struct sockaddr、struct sockaddr_in,這兩者通常轉換使用;
在Windows下面名稱都是大寫,而在Linux下為小寫
常用:
Linux下:
sockaddr_in destAddr;
destAdd.sin_family=AF_INET;
destAddr.sin_port=htons(2030);
destAddr.sin_addr.s_addr=inet_addr("192.168.1.1");
Windows下:
SOCKADDR_IN destAddr;
destAddr.sin_addr.S_un.S_addr=inet_addr("192.168.1.1");
但結構體中成員的名稱不同
Windows中結構體成員
struct sockaddr_in {
short sin_family;
u_short sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};
struct sockaddr {
u_short sa_family;
char sa_data[14];
};
struct in_addr {
union {
struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;
struct { u_short s_w1,s_w2; } S_un_w;
u_long S_addr;
} S_un;
};
下面的一些宏可以使windows下的程序移植到linux下(通過類型的重新定義,使代碼具有linux和windows下的移植性)
[cpp] view plain
#ifdef WIN32
typedef int socklen_t;
typedef int ssize_t;
#endif
#ifdef __LINUX__
typedef int SOCKET;
typedef unsigned char BYTE;
typedef unsigned long DWORD;
#define FALSE 0
#define SOCKET_ERROR (-1)
#endif
6)獲取錯誤碼
windows下getlasterror()/WSAGetLastError()
linux下errno變數
7)設置非阻塞
windows下ioctlsocket()
linux下fcntl() <fcntl.h>
8)send函數最後一個參數
windows下一般設置為0
linux下最好設置為MSG_NOSIGNAL,如果不設置,在發送出錯後有可 能會導致程序退出。
9)毫秒級時間獲取
windows下GetTickCount()
linux下gettimeofday()
10)數據類型的一些轉化
通用的:
小端到大端(網路協議使用)的轉換:htonl, htons
點分十進制IP和整數之間的相互轉換:inet_addr()(該函數將點分十進制轉為整數),inet_aton(),inet_ntoa(),inet_pton()(linux下獨有 該函數可以實現相互之間的轉換)
使用到的頭文件不相同,linux下用man命令查詢。
另外注意:
linux下使用的套接字為伯克利套接字,因此在select()函數的使用上(第一個參數的設置)也有區別;
windows下為了與伯克利套接字匹配,第一個參數是無所謂,一般可設為0;
int maxfdp是一個整數值,是指集合中所有文件描述符的范圍,即所有文件描述符的最大值加1,不能錯!
3、多線程
多線程: (win)process.h --〉(linux)pthread.h
_beginthread --> pthread_create
_endthread --> pthread_exit

『捌』 linux socket 編程

去查一下select系統調用。

select的read set那個參數,可以包含一個socket和一個pipe(Linux下叫做fifo,你信號用的是fifo傳遞嗎?),反正兩個在LInux下都是「文件描述符」,同時select函數可以在最後一個參數設置超時。
這樣可以么?

熱點內容
ss怎麼用安卓 發布:2024-03-28 18:51:39 瀏覽:687
腳本注入到其他軟體運行 發布:2024-03-28 18:30:02 瀏覽:720
網易我的世界皮膚能用到伺服器嗎 發布:2024-03-28 18:24:44 瀏覽:804
access資料庫數據類型 發布:2024-03-28 18:16:04 瀏覽:301
安卓界面如何變成蘋果手機界面 發布:2024-03-28 18:07:17 瀏覽:742
方舟手游如何卡安卓大廳會員 發布:2024-03-28 17:52:37 瀏覽:241
空域銳化演算法 發布:2024-03-28 17:52:32 瀏覽:500
虎牙安卓版是什麼意思 發布:2024-03-28 17:43:10 瀏覽:861
電腦改成雲伺服器 發布:2024-03-28 17:37:50 瀏覽:266
文件夾審計 發布:2024-03-28 17:08:20 瀏覽:242